CI/CD and Release Process

July 3, 2026 · View on GitHub

GitHub Actions workflows

Two workflows live in .github/workflows/.

ci.yml — build, lint, test, container E2E

JobCommandGates on
Checkcd src && cargo check --workspacecompile errors
Formatcd src && cargo fmt --all -- --checkrustfmt drift (fails on any diff)
Clippycd src && cargo clippy --workspaceerrors only — style warnings are shown but do not fail CI (see the note in the job)
Testcd src && cargo test --workspaceany failing test
Docker Buildbuilds Dockerfile.builder → extracts binaries → builds Dockerfile.core + per-NF Dockerfile.nfimage build failures (needs the sibling nextgsim checkout)
Docker E2Ebrings up the 5GC stack (mongodb, nrf, ausf/udm/udr/pcf/nssf/bsf, amf/smf/upf) and health-checks NRF/AMFstartup / health failures
Docker E2E (EPC)brings up the 4G EPC stack from docker-compose-epc.yml and inspects hss/pcrf/sgwc/sgwu/mmestartup / health failures

Docker jobs are opt-in. docker-build (and the dependent docker-e2e/docker-e2e-epc) run only on manual workflow_dispatch (Actions tab → Run workflow), not on push/PR — they recompile both workspaces in a container and need a cross-repo checkout, so they are too heavy/fragile for every commit. The fast gate (Check/Format/Clippy/Test) protects every push/PR.

Test/Clippy depend on Check; the two Docker E2E jobs depend on Docker Build.

The Test job runs cargo test --workspace at the runner's default parallelism. Tests that touch process-global NF state (a <nf>_context_init or std::env::set_var) must serialize on their crate's test_support::CONTEXT_GUARD, or they race and flake here — see docker/rust/CI.md and the per-crate test guards.

The richer matched-sim data-plane E2E (registration + PDU session + GTP-U ping) is not run by ci.yml; it is the one-command docker/rust/e2e.sh (documented in docker/rust/CI.md).

pages.yml — documentation site

Deploys docs/ to GitHub Pages (runs docs/scripts/update-api-docs.sh, uploads docs/). Triggered only when a GitHub release is published (on: release: [published]) so the site tracks the last release, plus workflow_dispatch for a manual re-deploy — it does not redeploy on every docs/** push.

Branch triggers

Both workflows run on the default release branch main and on the development branch initial_commit:

on:
  push:    { branches: [initial_commit, main] }
  pull_request: { branches: [initial_commit, main] }

(ci.yml on push + PR to either branch. pages.yml is not branch-triggered — it deploys the docs site when a release is published; see below.)

Local pre-push gate (mirror of CI)

Run from src/ in both repos before pushing:

cargo fmt --all -- --check      # Format
cargo check --workspace         # Check
cargo clippy --workspace        # Clippy (errors only)
cargo test --workspace          # Test

Optionally the full data-plane E2E: cd docker/rust && ./e2e.sh.

Cutting a release

  1. Ensure main (or the release branch) is green in CI and the matched-sim E2E passes (docker/rust/e2e.sh → 84/84).
  2. Bump the workspace version in src/Cargo.toml ([workspace.package] version) if used, and per-crate versions as needed. Current: 0.1.0.
  3. Move the ## [Unreleased] section of CHANGELOG.md under a dated ## [X.Y.Z] heading; add a fresh empty Unreleased.
  4. Commit (Signed-off-by: Murat Parlakisik <parlakisik@gmail.com>), tag X.Y.Z, push the tag.
  5. Create the GitHub release from the tag, pasting the CHANGELOG section as the release notes: gh release create X.Y.Z --repo NextgCoreLab/nextgcore --title "NextGCore X.Y.Z" --notes-file <(...). Publishing the release fires pages.yml, which deploys the docs site for this version.

Honesty in release notes: keep the validation caveat — spec-text + golden-vector + strict-peer

  • matched-sim E2E, not TTCN-certified or third-party-interop tested. 6G/Rel-20 items are research prototypes (no frozen stage-3 spec).