|
| 1 | +# Continuous integration |
| 2 | + |
| 3 | +`workflows/ci.yml` is the entry point for pull requests, pushes to any branch or |
| 4 | +tag, and manual full runs. Contributors can validate changes in their own forks |
| 5 | +before opening an upstream PR, once GitHub Actions is enabled in the fork. |
| 6 | +Both push and PR runs select tests by changed paths. Updating a PR cancels its |
| 7 | +previous CI run; push and publishing runs are not cancelled in progress. |
| 8 | + |
| 9 | +The entry point calls `ci-java.yml`, `ci-python.yml`, `ci-docs.yml` and |
| 10 | +`ci-licensing.yml`. `publish-snapshot*.yml`, `release*.yml` and |
| 11 | +`maintenance-stale-pr.yml` have separate publishing or maintenance triggers. |
| 12 | + |
| 13 | +## Selecting tests |
| 14 | + |
| 15 | +`tools/ci/plan.py` is the single source of path routing and the Java matrix. |
| 16 | +Its selection is shown in the workflow run summary. It uses the PR merge-base |
| 17 | +diff, or the entire before/after push diff. Both sides of a rename are included. |
| 18 | +Diffs are read from Git without a changed-file API limit. If a complete diff is |
| 19 | +unavailable (including a new branch), CI runs all suites. Manual dispatch also |
| 20 | +runs everything. |
| 21 | + |
| 22 | +PRs check changed files against a 1 MiB size limit. When the PR diff is unavailable, |
| 23 | +this check is skipped with a warning in the log and run summary so that existing |
| 24 | +oversized files do not block the full CI run. |
| 25 | + |
| 26 | +| Changed paths | Java tests | |
| 27 | +| --- | --- | |
| 28 | +| `paimon-spark/**` | Spark 3/4, core and integrations, Flink 1/Spark E2E | |
| 29 | +| `paimon-flink/**` | Flink 1/2, core and integrations, both E2E groups, Iceberg GA | |
| 30 | +| `paimon-e2e-tests/**` | Both E2E groups | |
| 31 | +| `paimon-eslib/**` | ESLib | |
| 32 | +| `paimon-iceberg/**` | Core and integrations, Iceberg GA | |
| 33 | +| `paimon-full-text/**` | Core and integrations, full text | |
| 34 | +| Shared modules, root/build configuration, unclassified source paths | All Java groups | |
| 35 | + |
| 36 | +Java changes retain the artifact licensing check. Changes to `docs/**` build the |
| 37 | +website; other Markdown-only changes skip expensive jobs. Changes to |
| 38 | +`paimon-python/**` and Java/Python `JavaPy*` test fixtures run Python checks. |
| 39 | +Root POM changes also run Python to validate its Java build. Mixed changes take |
| 40 | +the union of all required groups. Changes to CI routing or execution scripts |
| 41 | +validate every consumer, including Python and documentation. |
| 42 | + |
| 43 | +The core and integrations jobs deliberately still run for Spark/Flink changes: |
| 44 | +`paimon-spark-common` owns tests outside the Spark connector test jobs, |
| 45 | +`paimon-docs` tests engine configuration documentation, and Hive/Iceberg tests |
| 46 | +depend on Flink. Do not remove these jobs by looking only at the workflow name. |
| 47 | +`SparkE2eTest` runs in the JDK 8 E2E job and is disabled on JDK 11. |
| 48 | + |
| 49 | +## Builds and caches |
| 50 | + |
| 51 | +`tools/ci/run-java-tests.sh` owns Java build/test commands. Each group installs |
| 52 | +its selected modules and their dependencies with `-pl ... -am -DskipTests`, then |
| 53 | +tests only its modules. The test invocation does not clean away the first build |
| 54 | +or run both `test` and `verify`. Normal Maven checks remain enabled. |
| 55 | + |
| 56 | +Java dependency caches are isolated by suite, JDK and Scala. This prevents a |
| 57 | +small group's cache from permanently starving other groups of their dependencies. |
| 58 | +Failed Java jobs upload Surefire reports with a seven-day retention period. |
| 59 | +Python builds only the Java modules used by the mixed-language tests and their |
| 60 | +dependencies; its Python version and compatibility coverage is preserved. |
| 61 | + |
| 62 | +## Required checks and maintenance |
| 63 | + |
| 64 | +Configure branch protection to require **CI result** when adopting this layout. |
| 65 | +Remove any requirements referring to the retired individual workflow/job names. |
| 66 | +The result job always runs and requires the planner and every selected group to |
| 67 | +succeed. Unselected groups must be skipped. A planner failure, failed test, |
| 68 | +unexpected skip or cancellation cannot produce a green result. |
| 69 | + |
| 70 | +Every run validates the workflow syntax with pinned actionlint 1.7.11 and runs |
| 71 | +the routing/command tests before starting expensive jobs. Locally: |
| 72 | + |
| 73 | +```sh |
| 74 | +python3 -m unittest discover -s tools/ci -p 'test_*.py' |
| 75 | +actionlint -shellcheck= -pyflakes= |
| 76 | +CI_DRY_RUN=true bash tools/ci/run-java-tests.sh spark3 2.12 8 |
| 77 | +``` |
| 78 | + |
| 79 | +When adding an engine version, update both the matrix in `plan.py` and the |
| 80 | +module lists in `run-java-tests.sh`, including the core exclusions where needed. |
| 81 | +Add behavioral tests for any new routing boundary and retain shared-dependency |
| 82 | +fallbacks. Use a manual CI run to validate the complete matrix before adopting |
| 83 | +changes to build profiles or test ownership. |
0 commit comments