Skip to content

CAMEL-23492: Replace npm/Yarn/Gulp doc build with a Maven plugin#23198

Merged
davsclaus merged 3 commits into
apache:mainfrom
ammachado:CAMEL-23492
May 15, 2026
Merged

CAMEL-23492: Replace npm/Yarn/Gulp doc build with a Maven plugin#23198
davsclaus merged 3 commits into
apache:mainfrom
ammachado:CAMEL-23492

Conversation

@ammachado
Copy link
Copy Markdown
Contributor

@ammachado ammachado commented May 13, 2026

Description

TL;DR: Replaces the Node/Yarn/Gulp pipeline in docs/ with a new
prepare-doc-symlinks goal in camel-package-maven-plugin. Same Antora
source tree, byte-for-byte equivalent output (verified by snapshot diff),
no Node toolchain. Net −5,782 lines.

CAMEL-23492: Replace npm/Yarn/Gulp doc build with a Maven plugin

Replaces the Node.js/Yarn/Gulp pipeline in docs/ with a new prepare-doc-symlinks goal in camel-package-maven-plugin, and removes the Node toolchain entirely (package.json, yarn.lock, .yarnrc.yml, .yarn/, gulpfile.js).

The new mojo ports the three responsibilities of docs/gulpfile.js:

  1. Clean + create relative symlinks for .adoc, image and .json files from components/**, core/**, dsl/** into the Antora source tree under docs/components/modules/... and core/camel-core-engine/src/main/docs/modules/eips/....
  2. Generate sorted/grouped nav.adoc files from docs/*-nav.adoc.template, using each file's :doctitle: and optional :group:. Sort order matches the original gulp compare() (case-insensitive, summary-before-group), with a filename tiebreaker for TimSort transitivity.
  3. Extract include::{examplesdir}/... references from each linked .adoc and symlink the referenced examples under components/modules/ROOT/examples/....

Wiring changes:

  • docs/pom.xml: removes the frontend-maven-plugin block; adds a camel-package-maven-plugin prepare-doc-symlinks execution bound to generate-resources before the existing xref-check. The ${skipOnUnsupported} property is now read by the mojo as <skip>.
  • Root pom.xml: drops the now-unused .yarn / yarn.lock / yarn*.cjs Apache RAT excludes.

Cross-platform notes:

  • Windows symlinks: Files.createSymbolicLink requires Developer Mode or Administrator. The mojo tries a real symlink first and falls back to a plain file copy on FileSystemException, logging once per build (matches the vinyl-fs behaviour gulp had).
  • Glob semantics: JDK PathMatcher has *, **, ?, {a,b} and character classes but no extglob !(...). gulp negations are expressed as excludes lists per KindSpec, post-filtered by the walker. The {,**/}*.json brace form is used where gulp's **/*.json matched across zero intermediate dirs.
  • Locale-insensitive sort: Locale.ROOT is used for case-folding.

Verification:

  • Byte-for-byte equivalence: snapshot the symlink/nav tree on main and on this branch and diff them — empty diff means no regression. Snapshot command is embedded in the test class Javadoc. Locally on macOS the diff is 0 lines.
  • mvnd test -pl tooling/maven/camel-package-maven-plugin -Dtest=PrepareDocSymlinksMojoTest: 12/12 pass. Tests cover replaceBlock, extractTitle, and NavComparator (incl. transitivity).
  • mvnd -pl docs generate-resources -Dci.env.name=local: succeeds; no Node / Yarn downloaded.

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • I checked that each commit in the pull request has a meaningful subject line and body.
  • I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.

Claude Code on behalf of Adriano Machado

@ammachado ammachado marked this pull request as ready for review May 13, 2026 19:09
@github-actions
Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

🧪 CI tested the following changed modules:

  • docs
  • tooling/maven/camel-package-maven-plugin

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.

Build reactor — dependencies compiled but only changed modules were tested (2 modules)
  • Camel :: Docs
  • Camel :: Maven Plugins :: Camel Maven Package

⚙️ View full build and test results

components.asciidoc = new KindSpec(
List.of(
"core/camel-base/src/main/docs/*-component.adoc",
"components/*/src/main/docs/*-component.adoc",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've used this syntax to limit the number of subtrees the file walker can reach, matching gulpfile.js's behavior. Is this really necessary?

Copy link
Copy Markdown
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

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

Review: CAMEL-23492 - Replace npm/Yarn/Gulp doc build with Maven plugin

Overall Assessment: Well-executed port. Removing the Node.js toolchain eliminates a significant external dependency and simplifies the build. The byte-for-byte equivalence verification is the right way to validate a port like this. The code is well-structured with good Javadoc explaining design decisions.

Recommendation: Approve with minor fix needed.

Strengths

  • Clean removal of the entire Node toolchain (yarn 3.2.3, gulpfile, package.json, yarn.lock) — net -5,782 lines
  • Byte-for-byte equivalence verification provides strong confidence
  • Windows symlink fallback handling (matches vinyl-fs behavior)
  • Good unit tests for the trickiest logic — NavComparator transitivity, template substitution, title extraction
  • The NavComparator actually fixes a latent bug in the gulpfile's compare() which was not antisymmetric (returned 1 when both titles were equal, violating the comparator contract). The filename tiebreaker makes the ordering total and stable.

Issue to fix

FQCN usage for java.io.File: Lines 92 and 100 of PrepareDocSymlinksMojo.java use java.io.File as a fully-qualified type instead of importing it. Please add import java.io.File; and use the simple class name — this follows the project's import style convention.

Minor observations (non-blocking)

1. Subtle glob differences from gulpfile (non-observable)

  • "others" depth: The mojo includes components/*/*/*/src/main/docs/*.adoc for the "others" group, while the gulpfile only matches up to 2 levels ({*,*/*}). Currently produces identical output (no 3-level non-component adoc exists), but is slightly more liberal.
  • PRUNED_DIRS: The mojo prunes .camel-jbang by exact name match, while the gulpfile uses .camel-jbang* glob (would also exclude .camel-jbang-work etc.). Not currently observable.

Both are academic — the byte-for-byte diff proves equivalence on the current tree.

2. Non-recursive nav file scanning: createNav() uses Files.list() (flat) while the gulpfile uses **/*.adoc (recursive). Not a problem since all symlinked files are flat, but worth noting the assumption.

Test Coverage

The tests cover the trickiest logic well (replaceBlock, extractTitle, NavComparator transitivity). The remaining methods (matchesJsonFilter, clean, walk, createExampleSymlinks) are covered by the byte-equivalence diff — reasonable tradeoff.


Claude Code on behalf of Guillaume Nodet

@ammachado ammachado marked this pull request as draft May 14, 2026 01:04
@ammachado
Copy link
Copy Markdown
Contributor Author

Pulling back to review

@ammachado
Copy link
Copy Markdown
Contributor Author

Update on review items and a latent issue surfaced by improved logging

Pushed changes addressing the review:

  • FQCN java.io.File (lines 92/100): already imported at line 19 and used as simple File. No change needed.
  • "others" depth */*/*: already tightened to {*,*/*} to match gulpfile. No change needed.
  • PRUNED_DIRS .camel-jbang*: renamed to PRUNED_DIR_PREFIXES; now matches exact name or <name>-... form, pruning .camel-jbang-work alongside .camel-jbang, matching the original glob intent.
  • Flat createNav scan: added a comment noting the flat scan is equivalent to gulp's **/*.adoc because the prior symlink step flattens.

Additional improvements made while verifying parity:

  • createNav now logs → generated <path>/nav.adoc with N entries (gulp logged this; the mojo was silent).
  • createSymlinks / createExampleSymlinks deduplicate by destination path and log (from N sources) when occurrences differ — exposing basename collisions and duplicate include::{examplesdir} references that
    previously inflated the counts.

Latent issue surfaced (pre-existing on main, out of scope for this PR):

The new logging revealed 4 basename collisions in the dataformats group, where the Jackson 3.x components (camel-jackson3*) ship doc/JSON files with the same names as their Jackson 2.x counterparts
(camel-jackson*). The alphabetically-later Jackson 3 version overwrites the Jackson 2 one in docs/components/modules/dataformats/{pages,examples/json}:

Filename Jackson 2.x Jackson 3.x
jackson-dataformat.adoc / jackson.json camel-jackson camel-jackson3
jacksonXml-dataformat.adoc / jacksonXml.json camel-jacksonxml camel-jackson3xml
avroJackson-dataformat.adoc / avroJackson.json camel-jackson-avro camel-jackson3-avro
protobufJackson-dataformat.adoc / protobufJackson.json camel-jackson-protobuf camel-jackson3-protobuf

The effect is visible on the public dataformats index — the "JSON Jackson" entry on https://camel.apache.org/components/next/dataformats/index.html resolves to the Jackson 3 page rather than Jackson 2:

image

This collision exists on main with the gulp pipeline too; filesystem snapshot diff between gulp's output on main and the new mojo's output remains empty (1212 == 1212 entries).

Verification: formatter:format, impsort:sort, mvn install -Psourcecheck, 12 unit tests, and mvn -Pregen generate-resources all pass. Filesystem parity with gulp on main confirmed via
tools/snapshot-doc-symlinks.sh.

Claude Code on behalf of Adriano Machado

@ammachado ammachado marked this pull request as ready for review May 14, 2026 03:05
@davsclaus
Copy link
Copy Markdown
Contributor

about jackson vs jackson3, then lets tackle this in another PR. We should skip the jackson3 so we keep it as today. The jackson3 are special for SB4 and will eventually replace when we drop jackson2 later - but today too much is still jackson2 dependent.

@davsclaus
Copy link
Copy Markdown
Contributor

There are uncommitted changes
HEAD detached at pull/23198/merge
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: docs/tools/snapshot-doc-symlinks.sh

ammachado added 3 commits May 14, 2026 10:23
Port docs/gulpfile.js to a new prepare-doc-symlinks goal in
camel-package-maven-plugin and remove the Node toolchain (package.json,
yarn.lock, .yarnrc.yml, .yarn/, gulpfile.js). Output is byte-for-byte
equivalent with the previous gulp pipeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: Adriano Machado <60320+ammachado@users.noreply.github.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
@davsclaus
Copy link
Copy Markdown
Contributor

LGTM

@ammachado do you mind creating a JIRA about the jackson2 vs 3 issue you identified and you are welcome to work on another PR to fix/improve this

@davsclaus davsclaus requested review from aldettinger and oscerd and removed request for aldettinger May 15, 2026 06:17
@davsclaus davsclaus merged commit ebb0d3d into apache:main May 15, 2026
7 checks passed
@ammachado ammachado deleted the CAMEL-23492 branch May 15, 2026 16:38
@ammachado
Copy link
Copy Markdown
Contributor Author

CAMEL-23531 was created to track JSON Jackson issue identified above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants