-
Notifications
You must be signed in to change notification settings - Fork 162
[RORDEV-1228] Move CI from Azure Pipelines to GitHub Actions (Ubicloud Linux + GitHub-hosted Windows) #1292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 32 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
e764494
Port heavy IT CI pipeline from Azure Pipelines to GitHub Actions
sscarduzio 9a608c4
Fix orchestration defects in the GH Actions port; move Windows to GH-…
sscarduzio 2f4c638
Apply adversarial-review findings to the CI port
sscarduzio c95e3fb
Fix container-job shell: default run steps to bash (source is a bashi…
sscarduzio d3c2a7c
Experiment: IT_PARALLELISM=2 (2 sharded IT JVMs per leg)
sscarduzio c155c8a
Fix sharded IT on fresh workspaces: shard filter only with explicit -…
sscarduzio e79e37e
Sweep k=3: it_linux on ubicloud-standard-8 (32GB, 10.7GB/shard) + per…
sscarduzio a19ee28
Fix sharded IT result-dir collisions: per-shard junitXml/binary/html …
sscarduzio e7c5c4a
Fix second shard race: children skip prebuildEsImage (parent already …
sscarduzio 6a6de91
Serialize nested Tooling-API builds across shard JVMs + sweep k=3 on …
sscarduzio b146208
Sweep k=4 on 16GB runner (k=3@16GB: ~24min avg, stable, 2x over basel…
sscarduzio 8a244d7
Sweep k=6 on 16GB (k=4: ~22min avg, flattening vs k=3's ~24)
sscarduzio f1004f1
Set IT_PARALLELISM=4: sweep optimum on ubicloud-standard-4
sscarduzio 8784bbe
Sweep k=5 probe on 16GB: the untested gap between k=4 (stable) and k=…
sscarduzio 0b4cfb0
Disable x-pack ML in all test ES containers; settle sweep at k=4
sscarduzio 98da2ab
Duration-balanced LPT shard packing + slim child gradle daemons + dev…
sscarduzio 3085ade
Iteration 2: premium-runner probe for it_linux + poll instead of fixe…
sscarduzio d3a37f1
Revert to standard-4: premium probe gave only ~15% (shards 16.7-19 vs…
sscarduzio ef06db9
Iteration 4: shard workers reuse prebuilt plugin zip + 30s staggered …
sscarduzio 58312fc
Iteration 5: hash packing back as default; balanced mode kept behind …
sscarduzio 98c59d6
Iteration 6: light jobs to free GH runners + free-vs-paid probe leg
sscarduzio 8d9ddd1
Iteration 7: Windows sharding (free box, k=3) + Blacksmith probe; dro…
sscarduzio ca3fba5
Iteration 8: memory-aware balanced sharding (Linux+Windows) + Windows…
sscarduzio 59f5003
Iteration 9: k=5 probe with 3 heavy-suite permits + shared Windows do…
sscarduzio a5b9672
Iteration 10: Windows speed blitz + fix racy ILM step tests
sscarduzio a89b5f1
Restore full PR test matrices (exit dev mode)
sscarduzio 967972a
Fix fleet OOM (k=5→4) and Windows cross-shard WireMock port collision
sscarduzio 1cdb1b3
Cut heavy-suite permits to 2 and strip unused ES modules from test boots
sscarduzio c98d688
Tier-1 ES node diet: node.processors=2, 64m code cache, single Netty …
sscarduzio c70459f
Revert "Tier-1 ES node diet: node.processors=2, 64m code cache, singl…
sscarduzio b3dd114
Extend audit-suite eventually window 15s->60s (flaked twice under sha…
sscarduzio 1234cb1
Review pass: fix stale comments, docs, Blacksmith leftovers, fd-leak …
sscarduzio fdc70f6
Retry container start once on the docker parent-image build race
sscarduzio fb290ce
Fix round-robin audit test race: probe sink recovery before asserting
sscarduzio 80e056f
Address review: SuiteSharder, FileLockSemaphore, RorShard, docs conso…
sscarduzio 4d33ec9
Harden two startup flakes: audit-sink recovery probe resends, openlda…
sscarduzio 7162af3
Bytecode reuse guard: force fresh compiles (--no-build-cache) on both…
sscarduzio dfb3851
Address review round 2: current-state CI doc, timings drift automatio…
sscarduzio 93bdf1a
ci: add --stacktrace to cve_check for debug output
0062a5b
ci: add --info to cve_check for NVD download debug output
1983345
fix(cve): use absolute path for DEPENDENCY_CHECK_DATA_DIR
2af180e
ci(gha): review round — optional_checks matrix, unit_tests_linux, es9…
sscarduzio 24ddf00
Merge origin/develop into feature/ubicloud-ci-port
sscarduzio 6dc6102
refactor(ci): maintainability pass — dedupe file locks, testable drif…
sscarduzio 72437c1
docs(tests-utils): cross-reference FileLockSemaphore <-> FileLocks (w…
sscarduzio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Custom self-hosted runner labels used by CI (Ubicloud for Linux; Windows uses GitHub-hosted). | ||
| # Registering them here silences actionlint's "unknown label" false positives. | ||
| self-hosted-runner: | ||
| labels: | ||
| - ubicloud-standard-4 # 4 vCPU / 16 GB — the only Ubicloud size CI uses |
Large diffs are not rendered by default.
Oops, something went wrong.
|
sscarduzio marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
sscarduzio marked this conversation as resolved.
Outdated
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| # Azure Pipelines → GitHub Actions port | ||
|
|
||
| `.github/workflows/ci.yml` ports `azure-pipelines.yml` to GitHub Actions. | ||
| Linux jobs run on **Ubicloud** (`ubicloud-standard-4` = 4 vCPU / **16 GB**) inside the | ||
| same `beshultd/ror-ci-toolchains` image; Windows jobs run on **GitHub-hosted | ||
| `windows-2025`** (free for public repos — the same VM family Azure used). | ||
|
|
||
| The **build logic is unchanged** — every Linux job still calls `ci/run-pipeline.sh` | ||
| with a `ROR_TASK`, exactly as Azure did. `run-pipeline.sh` and its sourced libs | ||
| contain no Azure-specific constructs (verified), so only the orchestration layer | ||
| was rewritten. All 54 `ROR_TASK` values referenced by the workflow exist in the script. | ||
|
|
||
| **Azure triggers are disabled** (`trigger: none`, `pr: none`, schedules removed) in the | ||
| same PR; the Azure pipeline stays manually runnable as a fallback until it's deleted. | ||
|
|
||
| ## Stage → job mapping | ||
|
|
||
| | Azure stage | GH job | Notes | | ||
| |---|---|---| | ||
| | SUPERSEDE_GUARD | — | replaced by `concurrency` (cancel-in-progress **for PRs only**; branch pushes queue, so an in-flight release is never cancelled — Azure `batch: true` semantics) | | ||
| | DISK_PROBE | — | dropped (Azure host-recon only; N/A on Ubicloud) | | ||
| | ES_S3_UP | `es_s3_up` | `newes/*` branches only; ordered **before** all check/test jobs, as on Azure | | ||
| | BUILD_TOOLCHAINS_IMAGE | `build_toolchains_image` | schedule + manual | | ||
| | TOOLCHAINS_VERIFY | `toolchains_verify` | | | ||
| | OPTIONAL_CHECKS (CVE) | `cve_check` | `continue-on-error`; monthly cache key (`yyyyMM`), Azure `Cache@2` semantics | | ||
| | REQUIRED_CHECKS | `required_checks` | 4-way matrix | | ||
| | TEST (unit) | `unit_tests` | | | ||
| | TEST (Linux IT ×3 jobs) | `it_linux` | **dynamic matrix** from `setup`: full 34-version set on develop/master/epic + manual, 10-version subset on PRs. Skipped legs never boot a VM. | | ||
| | TEST (Windows IT ×3 jobs) | `it_windows` | dynamic matrix: 7 versions on develop/master/epic, 3 on PRs, full 33 on manual `run_all_tests_on_windows` | | ||
| | TEST (Windows unit, manual) | `unit_tests_windows` | manual `run_all_tests_on_windows` only | | ||
| | BUILD_ROR | `build_ror` | PR only; gates on Linux **and Windows** results (Azure `succeeded('TEST')` parity) | | ||
| | DETERMINE_CI_TYPE | `determine_ci_type` | `!cancelled()` + explicit result checks — see below | | ||
| | UPLOAD_PRE_ROR | `upload_pre_ror` | pre-release, auto only | | ||
| | RELEASE_ROR (+ without-testing) | `release_ror` | `permissions: contents: write` for the tag push; `TRAVIS_BUILD_NUMBER=github.run_number` for the tag message | | ||
| | PUBLISH_MVN_ARTIFACTS (+ without-testing) | `publish_mvn` | master release only | | ||
|
|
||
| ### The skipped-needs trap (why release jobs check `needs.<job>.result` explicitly) | ||
|
|
||
| GitHub skips a job whose `needs` contains a skipped job (implicit `success()`). | ||
| The manual `release_without_testing` path *intentionally* skips the test jobs, so | ||
| `determine_ci_type` / `release_ror` / `publish_mvn` use `!cancelled()` plus explicit | ||
| two-arm conditions, mirroring Azure: | ||
|
|
||
| - **auto arm**: push to develop/master, `required_checks`/`unit_tests`/`it_linux`/`it_windows` | ||
| all `result == 'success'` | ||
| - **manual arm**: `workflow_dispatch` + `actionToPerform == 'release_without_testing'` + | ||
| `toolchains_verify.result == 'success'` | ||
|
|
||
| ## Trigger-scenario walk-through (regression table) | ||
|
|
||
| Which jobs run per trigger (✓ run / − skip), matching the Azure stage conditions: | ||
|
|
||
| | Job | PR | push develop | push master | push newes/* PR | dispatch: linux tests | dispatch: win tests | dispatch: release w/o testing | schedule | | ||
| |---|---|---|---|---|---|---|---|---| | ||
| | setup | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ||
| | build_toolchains_image | − | − | − | − | − | − | − | ✓ | | ||
| | toolchains_verify | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | − | | ||
| | es_s3_up | − | − | − | ✓ | − | − | − | − | | ||
| | cve_check | ✓ | ✓ | ✓ | ✓ | − | − | − | − | | ||
| | required_checks | ✓ | ✓ | ✓ | ✓ | − | − | − | − | | ||
| | unit_tests | ✓ | ✓ | ✓ | ✓ | ✓ | − | − | − | | ||
| | it_linux | ✓ (10) | ✓ (34) | ✓ (34) | ✓ (10) | ✓ (34) | − | − | − | | ||
| | it_windows | ✓ (3) | ✓ (7) | ✓ (7) | ✓ (3) | − | ✓ (33) | − | − | | ||
| | unit_tests_windows | − | − | − | − | − | ✓ | − | − | | ||
| | build_ror | ✓ | − | − | ✓ | − | − | − | − | | ||
| | determine_ci_type | − | ✓ | ✓ | − | − | − | ✓ (on develop/master ref) | − | | ||
| | upload_pre_ror | − | ✓ if `-pre` | ✓ if `-pre` | − | − | − | − | − | | ||
| | release_ror | − | ✓ if release | ✓ if release | − | − | − | ✓ if release | − | | ||
| | publish_mvn | − | − | ✓ if release | − | − | − | ✓ if release+master | − | | ||
|
|
||
| ## Azure feature translations | ||
|
|
||
| | Azure | GitHub | | ||
| |---|---| | ||
| | `$(System.AccessToken)` | `secrets.GITHUB_TOKEN` | | ||
| | `##vso[task.setvariable]` | `>> $GITHUB_OUTPUT` / `>> $GITHUB_ENV` | | ||
| | `##vso[...;isSecret=true]` (docker-hub-auth.sh) | `::add-mask::` — the script is now CI-aware (emitting the ##vso line on GH would have **printed** the secret) | | ||
| | `Cache@2` monthly CVE key | `actions/cache@v4` + `date +%Y%m` key | | ||
| | `DownloadSecureFile@1` (secret.pgp) | base64 secret `PGP_SECRET_KEY_B64`, decoded in-step | | ||
| | `PublishTestResults@2` | `actions/upload-artifact` of `**/TEST*.xml` on failure | | ||
| | PR-vs-branch matrix subsets (3 jobs per OS) | one dynamic matrix per OS from the `setup` job | | ||
| | `free-host-disk.sh` (`target: host`) | runs normally; `AGENT_ISSELFHOSTED=1` makes it a no-op (Ubicloud VMs have no Azure bloat to reclaim) | | ||
| | git tag push (persistCredentials) | `permissions: contents: write` on `release_ror` — **no SSH deploy key needed** | | ||
|
|
||
| ## Deliberate behavior differences vs Azure | ||
|
|
||
| - **`paths-ignore: '**/*.md'` is broader than Azure**, which could only exclude root-level | ||
| `.md` files plus the `docs`/`.claude` trees (Azure glob limitation — its own comment says | ||
| deeper exclusion was wanted). Here any md-only change anywhere skips CI. Markdown can't | ||
| affect build outputs, so this is the intent Azure couldn't express. | ||
|
|
||
| ## Deliberately dropped (and why) | ||
|
|
||
| - **DISK_PROBE** (and the `run_disk_probe` manual action) — Azure host-disk recon; irrelevant | ||
| on Ubicloud VMs. `ci/probe-host-disk.sh` stays in the tree for the Azure manual fallback. | ||
| - **SUPERSEDE_GUARD** + `ci/stale-azure-pipeline-runs-canceler.sh` — native `concurrency`. | ||
| - **Docker pre-clean / always()-reap steps** from the Azure IT template — both Ubicloud and | ||
| GH-hosted runners are ephemeral (fresh VM per job); there are no leftovers to reap and no | ||
| sibling jobs sharing a daemon. `run-pipeline.sh`'s SIGTERM trap still reaps on cancel. | ||
| ## IT parallelism (not in Azure — added during the port) | ||
|
|
||
| Azure ran each IT leg's suites serially in one JVM (~85–100 min/leg incl. queue). Here every | ||
| leg runs **4 sharded test JVMs** on its VM (`integration-tests:shardedTest`, `IT_PARALLELISM`), | ||
| cutting a leg to ~18–24 min. Windows runs 3 shards (native ES processes, per-shard port/dir/ | ||
| WireMock windows). Two safety mechanisms make this fit 16 GB: | ||
|
|
||
| - **Duration-balanced packing** (`ROR_BALANCED_SHARDS`): suites are LPT-packed into shards by | ||
| measured wall time (`integration-tests/suite-timings.json`) instead of name-hash, so no shard | ||
| becomes the long pole. Timings are advisory — suites without an entry default to 60s and still run. | ||
| - **`HeavySuiteGate`** (`ROR_HEAVY_SUITE_PERMITS`, currently 2): a machine-wide file-lock | ||
| semaphore capping how many multi-node-cluster suites boot containers concurrently across all | ||
| shard JVMs. Without it, level packing host-OOMs 16 GB runners. Crash-safe: an OOM-killed | ||
| worker's lock dies with its process. | ||
|
|
||
| Per-shard console logs upload as the `sharded-logs-*` artifact and per-shard JUnit XML as | ||
| `*-results` (both always, pass or fail). Measured limits, for whoever tunes this next: 5 workers or 3 permits exceed | ||
| either 16 GB (at 512m ES heaps) or the 4-vCPU boot-time budget — both were tried on isolated | ||
| probe runs and reverted. | ||
|
|
||
| ## Before first run — do these | ||
|
|
||
| 1. **Install the Ubicloud GitHub App** on the repo (Linux jobs). Windows needs nothing — | ||
| GitHub-hosted. Without Ubicloud, every Linux job queues forever. | ||
| 2. **Set secrets/variables**: `ci/github/set-secrets.sh` (17 secrets + 8 variables, see SECRETS.md). | ||
| 3. **Smoke-run**: `workflow_dispatch` → `run_all_tests_on_linux` on a branch validates | ||
| toolchains_verify + unit + full Linux IT without touching release paths. Watch the first IT | ||
| leg: testcontainers inside the `container:` job must reach the host Docker daemon | ||
| (Actions auto-mounts `/var/run/docker.sock`; Ubicloud provides host Docker). | ||
| 4. Azure is already trigger-disabled; it remains manually runnable from the Azure DevOps UI | ||
| as a fallback until you delete `azure-pipelines.yml` + `ci/azure-templates/`. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.