blob: c818ad08f1510e59ca94945435d486844caf7d65 [file] [view]
# CI policy
[HugeGraph-Server CI](../.github/workflows/server-ci.yml) is the single entry point for
PRs, supported branch pushes, weekly coverage and manual validation. Its preflight job
selects affected tests, reads the project Java version, checks CI policy and verifies
license headers and RAT. Selected Helm checks run as steps in preflight; other selected suites
run through reusable workflows in the same run.
CI results become advisory after [`.asf.yaml`](../.asf.yaml) is applied. It requests no required CI contexts
and retains one approving review. This protection change takes effect after the configuration
is merged and synchronized by Gitbox; verify live protection then. Failed tests keep their
real failed results. Valid selection and Java outputs allow selected tests to run even when
the preflight license checks fail.
Preflight keeps its real `check-license` name. The temporary `Server memory tests`
protection bridge has been removed after confirming both ASF and org master required
contexts are empty. Actual backend jobs are named `Server memory tests (Java ...)`
and `Server rocksdb tests (Java ...)`; their native checks report real execution.
## Coverage with selective tests
Each coverage upload has a stable test-group flag. The [Codecov configuration](../.github/codecov.yml)
enables [carryforward](https://docs.codecov.com/docs/carryforward-flags). When Codecov can
find an earlier flagged report in its recorded parent chain, it preserves that historical
report for unexecuted groups such as Commons, PD/Store and backends.
The PR comment explicitly marks carried-forward data. It is historical coverage,
not evidence that a skipped test ran; native job failures remain failures.
New flags need a complete initial baseline. The existing weekly full run supplies every
flagged group for that commit. Master pushes remain smoke-only and upload no coverage;
those commits can break Codecov's recorded parent chain. A fresh selective PR based on
such a commit is not guaranteed to inherit the weekly baseline, and its project report
may still be incomplete. Carryforward within an existing reported PR chain does not
prove this works for a fresh PR. Full and selected runs retain explicit report paths and
uploads; no extra collector runner or repeated master coverage tests are added.
## What runs
| Validation | Ordinary PR | Push to master | Weekly full run |
| --- | --- | --- | --- |
| Memory and RocksDB | Full unit, core and API tests when affected | No repeated full tests | Full tests |
| macOS ARM | Startup, JNI, graph read/write and restart smoke when affected; full core/API for platform inputs | Affected smoke | Full core/API |
| HBase and RISC-V | Directly related backend/platform or validation inputs only | No repeated tests | Full validation |
| PD, Store, HStore and Cluster | Affected modules and known consumers | Current-commit distributed smoke | Full group |
| CodeQL | Authentication, authorization, security, schema cache transactions, POM or CodeQL configuration inputs | No repeated scan | Full scan |
| Docker, Helm and dependency audit | Corresponding inputs | Corresponding deployment smoke or checks | Full validation |
macOS uses one `macos-15` ARM job for either smoke or full validation. Intel macOS is removed.
The weekly run uses `cron: '0 6 * * 1'` with `timezone: Asia/Singapore`: Monday at 06:00,
on the latest default-branch commit. GitHub may delay scheduled runs during high load;
see [schedule behavior](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule).
### Affected inputs
The rules live in [ci-policy.py](../.github/scripts/ci-policy.py). Ordinary Server changes
select both Memory and RocksDB, plus ARM smoke. They do not select the complete PD/Store group.
PD and Store changes select their own tests and downstream consumers; Commons and Struct
select their known shared consumers. HStore and Cluster additionally follow distributed
backend contracts, protocols, metadata, graph lifecycle and scheduling inputs. Distribution,
startup and RocksDB inputs select ARM full validation and their deployment consumers.
Unclassified paths or an unavailable diff/API conservatively select mainline coverage.
HBase and RISC-V remain limited to explicit related inputs, weekly coverage or manual selection.
The classifier uses paths, not PR titles or semantic interpretation of changed text.
Contract scripts explicitly select their executing suites without adding runtime consumers.
### Documentation
Documentation-only ordinary PRs allocate just the preflight CI runner. On the two trusted
master repositories, pushes also run the shared dependency producer and isolated writer so
that the exact event commit has a dependency baseline; other documentation-only pushes use
only preflight. This count excludes the non-test [Auto PR Commenter](../.github/workflows/auto-pr-review.yml), which runs
once when a PR opens. Scheduled and manual selections still run their requested suites.
Plain documentation includes regular-file root prose, README/AGENTS files and supported prose
or static images under `docs/`, including nested module documentation. Runtime resources,
configuration, source, fixtures, templates and executable or symbolic-link files do not qualify;
for example, a test fixture ending in `.txt` still selects its module's tests.
## Manual validation and reruns
Use **Actions → HugeGraph-Server CI → Run workflow**, select a branch and choose `test-set`:
| Test set | Validation |
| --- | --- |
| `dependencies` | Dependency inventory and PR review; on trusted master, generate and submit a baseline |
| `mainline` (default) | Full mainline modules, deployment/dependency checks and CodeQL; ARM smoke |
| `distributed` | Struct, PD, Store, HStore and Cluster, plus distributed smoke |
| `macos-arm` | ARM smoke and full RocksDB core/API tests |
| `hbase`, `riscv64`, `codeql` | The corresponding complete specialist validation |
| `full` | All retained suites, identical to weekly coverage |
Fork contributors run additional validation in their fork's Actions. The manual entry point
does not accept a PR number, apply labels or reuse another workflow's results.
Automatic retries are disabled. Use GitHub's native rerun controls for failed jobs or a run;
a rerun retains its original commit and event, subject to the preflight freshness checks.
## Java runtime compatibility
A positive suite passes only when its tests succeed and its current-run output has no
Java runtime compatibility errors. Server, PD/Store, Commons, Struct and Cluster test
steps capture both stdout and stderr before running `check-java-runtime-logs.sh`.
Startup and Console smoke tests also inspect their output before cleanup. Cluster nodes
forward their text runtime logs to the captured suite output before deletion.
Missing or unreadable required logs fail the check.
The gate rejects denied module access and unknown or removed JVM options, including
exceptions caught and printed by dependencies. Ordinary business errors and deliberate
negative fixtures are not compatibility failures. Native smoke additionally uses `--native`
for its existing native linkage checks.
Launchers and tests share each component's `jvm-module.options`: PD and Store open
`java.lang` for Hessian, while Console and dump-store reuse Server's existing options.
Required module options are independent of custom `JAVA_OPTIONS` or `-j` flags; Surefire
retains the JaCoCo agent. CI continues to use the project Java runtime and its existing
suite-selection and required-check policy.
## Freshness, runner use and budgets
PR selection uses the cumulative diff against the checked-out merge commit's base. A source
PR followed by a documentation-only commit still tests the cumulative source changes.
Preflight verifies that the event merge commit's second parent matches the current PR head.
A stale PR head fails preflight. Target-branch advancement alone does not invalidate a run.
Plans and selection summaries describe this run; previous results are never reused.
A new PR head or master push cancels the previous automatic run for that PR or master ref,
including its called workflows. Release/test branch pushes, manual runs, weekly runs and
explicit rerun attempts remain independent. Checks keep their real failed results; there
are no separate post-test aggregation runners or end-of-run metadata checks.
Startup contracts run inside RocksDB validation. Struct tests and their shell contracts run
inside the selected Store job, reusing its reactor build; a Struct-only selection retains
its own runner. RocksDB version compatibility runs once inside the first selected PD, Store
or HStore job, in that order. A push creating a branch has no previous revision; it
reports this explicitly and skips only the before/after compatibility comparison. These added steps
still execute after ordinary host-job failures;
a host timeout or cancellation can stop them. Helm uses preflight, whose total budget is
20 minutes. PR dependency review runs as the last step of the existing dependency job even
if its build or inventory check failed. Informational OpenSSF Scorecard display is disabled;
vulnerability checks and their failure threshold are unchanged. Store uploads Codecov data
after all Maven checks so downloaded checksum files cannot contaminate a later RAT scan.
These mergers remove four runner allocations from
a complete mainline PR run, without dropping checks; heavy module suites remain separate.
Docker's static checks, deployment contracts and current-image validation share one runner.
The Docker job has a 90-minute total budget, with 25 minutes for deployment contracts and
45 minutes for image build/runtime validation. Distributed smoke builds current PD, Store
and Server images and checks authentication, readiness and graph read/write. It does not
substitute published images for the current commit.
PD and Store reserve 45 and 70 minutes including their merged checks, rather than
sharing the previous 30/45-minute limits. The dependency job retains the existing inventory
budget; baseline-only builds keep a 60-minute limit. Commons has 20 minutes. Cluster has 120 minutes
for its two 45-minute test windows and build/diagnostics. Other budgets are in the workflows.
TinkerPop suites keep their dedicated branch policy: the source, target or push/manual branch
must start with `release-`, `test-` or `tinkerpop-`. Executed suites require non-empty reports
with actual tests.
Each separate job or matrix item requests a runner; steps within a job share one.
[Standard hosted runners are free for public repositories](https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories),
but [plan-dependent total and macOS concurrency limits](https://docs.github.com/en/actions/reference/limits#job-concurrency-limits-for-github-hosted-runners)
still apply. Reducing job allocations and long executions lowers shared-pool demand;
it does not guarantee a specific queue delay.
## Dependency baseline
The main CI coordinator selects the [shared dependency job](../.github/workflows/check-dependencies.yml)
for baseline production on every trusted master push and manual `dependencies` run on master.
Manual `mainline` and `full` runs keep all requested tests and inventory checks without
producing a baseline, so master advancement cannot skip or fail those checks. The job installs
the complete reactor once with Java 17 and `contents: read`, reusing `actions/setup-java`'s Maven cache. When the
path classifier also selects dependency inventory checks, those checks and baseline
production share this same installation instead of building the reactor twice. It generates
each module's resolved graph with Ferstl 4.0.3. The repository's
[stdlib serializer](../.github/scripts/dependency-snapshot.py) preserves the
[official Maven parser 6.0.1](https://github.com/actions/maven-dependency-submission-action/tree/1f666f7ac2ab7b72cd5e22eaf7f23c8a581db1db)
package URLs and relationships. Non-test scopes take precedence when Ferstl merges
scopes onto one artifact; only test-only artifacts are development dependencies.
Every tracked POM must have a graph; empty aggregator manifests are allowed, but a
completely empty inventory fails. Fixture validation shares preflight and the dependency job;
there is no separate validation runner. The [reusable submission workflow](../.github/workflows/submit-dependencies.yml)
contains only the isolated writer. Only `apache/hugegraph` (not a fork) and the explicitly allowed
`hugegraph/hugegraph` test fork on `refs/heads/master` can run the submission job,
which alone has `contents: write`. PRs, other repositories and other refs cannot
run the writer. Maven inherits no submission token, and checkout does not persist
credentials. The same read-only job separately resolves all module dependency
scopes with Apache Maven Dependency Plugin 3.8.1 `tree` JSON, sharing the installed
reactor while keeping the two resolvers and JSON reports independent. Its
[stdlib inventory adapter](../.github/scripts/dependency-inventory.py) records each POM's
package URLs, scopes and direct/indirect relationships independently of the Ferstl
parser. The writer requires exact equality with that inventory, including empty
aggregators; a graph retaining one direct package while omitting another fails.
The global runtime/shipped jar filename inventory has a different scope and does
not replace this per-module check.
A pinned `actions/upload-artifact` transfers `snapshot.json` and `inventory.json`
as separate artifacts. The fresh writer runner uses fixed inline stdlib Python to
verify the successful `dependency_license / dependency-check` producer in the same
`server-ci.yml` run and both artifact/run/attempt/SHA identities
before downloading. It bounds ZIP and JSON sizes, checks each archive digest,
and reads only its one expected regular JSON member in memory. Duplicate members,
paths and symlinks fail; no archive members are extracted to disk. A signed storage
redirect is fetched without forwarding GitHub Authorization, and further redirects
are refused. The writer does not check out the repository, run Maven, or execute
downloaded code. The first-party upload action is permitted by the
[ASF Actions policy](https://infra.apache.org/github-actions-policy.html).
Checkout and snapshot use the event commit SHA. Master is checked before install
and again after both reports are generated; a stale run fails. A newer master
push cancels the older master run because only the current master can submit.
Manual and scheduled runs use separate concurrency groups and cannot cancel automatic
master pushes. Every trusted master push still selects the producer without path filters,
so unrelated changes also can receive an exact-SHA baseline. Such a push still requires
one complete reactor install; merging jobs removes duplicate builds, not that inherent cost.
The writer
checks the run attempt, successful producer, artifact ID/name, JSON schema,
detector/correlator and source SHA/ref. It verifies all manifest paths against the
event commit's source tree, rejects empty or mismatched inventory, and checks master
immediately before and after submission. Snapshots retain the checked event SHA
if master advances during submission; that run fails its final freshness check.
If submission fails, use **Re-run all jobs** or start a fresh `workflow_dispatch`
of **HugeGraph-Server CI**, choosing `dependencies` on master. **Re-run failed jobs**
keeps the older generation artifact, which the
writer rejects because both reports must be produced in the same run attempt.
If a PR `dependency-review` failure reports 0 base snapshots, rerun that job only
once the same repository's **HugeGraph-Server CI** run has successfully submitted the
baseline for the event's
exact `pull_request.base.sha` (not the branch's merge base or a newer master tip).
If that SHA has no successful baseline, including a skipped or superseded run,
rerunning the review alone cannot supply it. The producer supports only the current
master tip; cancelling an older run does not backfill its earlier PR events.
To recover, wait until the current master has a successful baseline in the same
repository. Normally merge that master into the PR branch (or use Update branch)
and push the update to create a new PR event. Confirm that the new event's
`pull_request.base.sha` is the SHA with the successful baseline, then use that
new dependency-review run. Rerunning the old job retains its old event payload
and cannot move its base SHA to the submitted baseline.
A fixed master-only correlator keeps successive baseline snapshots in the
same stream within each repository; ASF and org inventories are independent. The writer's
identity is separate from automatic PR submissions so they cannot replace its baseline.
The [snapshot API](https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository)
requires Contents write permission. The writer also has Actions read permission
to verify run and artifact metadata. Snapshot metadata identifies the repository
adapter rather than claiming that the combined generation/submission action ran.
This producer supplements the existing dependency review and shipped-inventory
checks without changing their severity, license rules or inventory. Merging the
workflow does not prove that either repository has a baseline: verify each repository's
first master submission, including its SHA/ref, non-empty module manifests and a real
dependency-review comparison against that baseline. Until then, that repository's baseline
acceptance remains open. This workflow changes no repository settings.
Dependency snapshot producer and submission-workflow changes select dependency checks.
Snapshot fixture tests run in the entry job; they do not select runtime suites. Local Helm
and RocksDB compatibility action changes select their existing owners. Changes to the CI
classifier still receive conservative mainline validation.