Skip to content

[CI][ROCm] Add AITER_NIGHTLY to Pipeline Generator - #777

Draft
josh-schell-amd wants to merge 24 commits into
mainfrom
aiter-nightly-ci
Draft

josh-schell-amd wants to merge 24 commits into
mainfrom
aiter-nightly-ci

Conversation

@josh-schell-amd

@josh-schell-amd josh-schell-amd commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Purpose

Make AITER_NIGHTLY=1 work in the ci pipeline (the Python pipeline generator), not just in amd-ci (bootstrap-amd.sh + test-template-amd.j2).

Since vllm-project/vllm#61939 and #820, vLLM's build.sh installs the AITER nightly wheel in image-build-amd. It picks the newest wheel that matches the image's ROCm, torch and Python, or uses the pip spec in AITER_SPEC. rocm_ci_repo() already sends AITER nightly builds to rocm/vllm-dev, never rocm/vllm-ci. So with AITER_NIGHTLY=1, the ci pipeline already builds the right image. What it lacked was step selection: it still ran a normal main build, with CUDA and MI250 jobs, test-selector and source-file gating, NOAUTO blocks and the docs-only skip.

What this PR does

With AITER_NIGHTLY=1, the generator runs the build as a build of named steps, the same mechanism as a retry build (VLLM_CI_ONLY_STEP_KEYS). aiter_nightly_step_keys() names the steps:

  • Only the AMD lane. The AMD build steps (amd_cpu) and the GPU jobs on the archs vLLM builds AITER for (AITER_ROCM_ARCH in Dockerfile.rocm_base): gfx942 (MI300, MI325) and gfx950 (MI355). Native AMD steps and amd- mirrors are both included. Everything else, CUDA and MI250 included, is dropped. amd-ci picks by amdgfx942nightly/amdgfx950nightly tags; the generator picks by device arch, using a new arch field on AmdDeviceConfig.
  • Nothing is gated. Every named step runs, even with NOAUTO=1, optional steps included. The test selector is skipped, and a docs-only last commit does not skip the build.
  • Retry builds. With VLLM_CI_ONLY_STEP_KEYS set, the named steps must be AITER nightly steps.
  • Guards. Generation fails with an error annotation, before anything is uploaded:
    • when the nightly's steps, or their prerequisites, include any other step (a kept job depending on a dropped one, or a retry naming a dropped step);
    • when TORCH_NIGHTLY and AITER_NIGHTLY are both set;
    • when the vLLM checkout has no .buildkite/scripts/rocm/build.sh, since an older checkout would otherwise test the stock AITER.
  • No recording. The test-selector recorders (VLLM_CI_KERNREC, VLLM_CI_KERNREC_AMD, VLLM_CI_FNREC) are off on the nightly, even if set: its AMD-only runs on an unreleased AITER would mislead the selector's records.

vLLM's build steps are used as they are: refresh-rocm-base-amd → image-build-amd (build.sh rocm ci). Both get ROCM_CI_REPO=rocm/vllm-dev, and GPU pods run rocm/vllm-dev:build-$BUILDKITE_BUILD_ID. As with any named-steps build, the image steps are not uploaded early (#864); they go up with the pipeline. On a PR build, pre-commit still runs and gates the AMD jobs, as on any PR build.

If AITER_NIGHTLY is unset, the pipeline is exactly as before.

Also fixes a retry-build bug on main: a retried AMD GPU job whose depends_on named image-build (e.g. from a group default) was uploaded without image-build-amd and refresh-rocm-base-amd, waiting on a step not in the build. Retry builds now expand AMD dependencies the way the uploaded job declares them.

Changes since the first revision

Rebased onto main after #820, #864, #737 and #871. The earlier aiter-nightly-amd overlay step is gone: it ran aiter-nightly-overlay.sh after ensure-ci-base-amd, and vLLM main has neither anymore, so build.sh now does that job.

Verification

  • buildkite/tests/pipeline_generator/test_aiter_nightly.py runs generate() end to end on one step list with every step shape (unkeyed, A100 mirror, dind mirror, mirror without a device, AMD job with a mirror, inherited image-build, sharded jobs):

    • the nightly's exact job set, with and without NOAUTO: nothing deferred, no early upload, no dangling dependency, vLLM's build steps into rocm/vllm-dev, runtime sharding (Fix automatic sharding for standalone AMD jobs and selected tests #871) only for kept jobs, a docs-only diff not skipping it, recorders off even when set, and the selector record;
    • the stock pipeline with AITER_NIGHTLY unset or not 1;
    • a retry build of a kept job;
    • every guard above: an error annotation, no upload, no pipeline file.

    Each guard and filter was mutation-checked: removing it fails a test.

  • pytest buildkite/tests: the same results as main plus the new tests.

  • Rendering the real vLLM ci pipeline: with AITER_NIGHTLY unset, the output is byte-identical to main across 9 variants (default, NOAUTO, PR build, TORCH_NIGHTLY, AITER_NIGHTLY=0/true, early upload, retry builds of a native AMD job and a mirror). With AITER_NIGHTLY=1: 210 jobs, none deferred, no dangling dependencies, with or without NOAUTO.

  • Buildkite ci run with AITER_NIGHTLY=1: pending

🤖 Generated with Claude Code

Comment thread README.md Outdated

A retried overlay step reinstalls the wheel its first attempt chose.

The pipeline generator does the same when `AITER_NIGHTLY=1` is set on a build it generates, such as `ci`. It chooses jobs by GPU instead of by tag: the AMD build steps and the GPU jobs on gfx942 (MI300, MI325) and gfx950 (MI355). Every other step, CUDA included, is dropped. See the [pipeline generator README](buildkite/pipeline_generator/README.md#environment-variables).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

blocking comment

@josh-schell-amd josh-schell-amd changed the title Aiter nightly ci [CI][ROCm] Add AITER_NIGHTLY to Pipeline Generator Oct 13, 2026
@josh-schell-amd
josh-schell-amd marked this pull request as ready for review October 13, 2026 18:53
Comment thread buildkite/pipeline_generator/amd.py Resolved
def test_overlay_does_not_change_the_steps_it_was_given():
steps = _build_steps()
amd.apply_aiter_nightly(steps)
assert steps == _build_steps()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This test looks trivial, we can remove it

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ack

return buildkite_step.convert_group_step_to_buildkite_step(group_steps(steps))


def test_nightly_rejects_a_kept_job_depending_on_a_dropped_one(fake_global_config):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can consolidate this test with test_generate_fails_on_a_dropped_dependency

@josh-schell-amd
josh-schell-amd force-pushed the aiter-nightly-ci branch 2 times, most recently from 9fcb6f5 to e0f2fa7 Compare October 20, 2026 16:54
@micah-wil

Copy link
Copy Markdown
Contributor

https://buildkite.com/vllm/ci/builds/96238/list <- AITER_NIGHTLY=1 (the TG failures there are expected and unrelated)

https://buildkite.com/vllm/ci/builds/96253/list <- AITER_NIGHTLY unset

cc @AndreasKaratzas can you take a look?

@josh-schell-amd
josh-schell-amd marked this pull request as draft October 29, 2026 19:06
@josh-schell-amd

Copy link
Copy Markdown
Collaborator Author

Setting back to draft with changes to rocm base image and AITER_NIGHTLY being moved in there from vllm-project/vllm#61939 being merged, need to reevaluate this PR.

josh-schell-amd and others added 16 commits November 2, 2026 12:33
…LY=1

The pipeline generator's version of the amd-ci AITER nightly (#733).

- Add aiter-nightly-amd after ensure-ci-base-amd. It runs vLLM's
  aiter-nightly-overlay.sh and retries only exit 1/2, never the AITER
  failures 10/11.
- image-build-amd waits for it, builds on its image, and uses the
  aiter-nightly cache branch.
- Run only the AMD lane, and in it only native jobs on gfx942/gfx950
  (MI300, MI325, MI355). Drop DinD jobs, which start from the stable
  ci_base and would test the stock AITER; annotate any dropped.
- Nothing is gated, docs-only changes do not skip the build, and
  TORCH_NIGHTLY cannot be set alongside it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
…NOAUTO

Fixes from review of the generator's AITER nightly:

- Keep DinD jobs. They do test the nightly: run-amd-test.sh builds their
  image on the ci_base recorded in the vLLM artifact, which in the nightly
  is the overlay's. Dropping them guarded against nothing.
- Fail generation, with an annotation, if a job the nightly keeps depends
  on a step it drops, rather than upload a dangling depends_on.
- Check the AITER nightly before NOAUTO, so nothing in it is gated, as in
  test-template-amd.j2.
- ci_selector's generator contract test pins the new branch off; it read
  a config without aiter_nightly and raised KeyError.
- Test generate() end to end: the uploaded YAML, the $$ in the image
  build, and the annotations.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
- Generator README: AMD CPU build steps run too, DinD jobs are kept,
  NOAUTO does not gate the nightly, and a kept step depending on a
  dropped one fails generation. DOCS_ONLY_DISABLE and
  VLLM_CI_ONLY_STEP_KEYS note how the nightly changes them.
- Root README: the AITER_NIGHTLY row describes the amd-ci template and
  the generator separately; they select differently.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
check_aiter_nightly_dependencies repeated the rules for which steps the
nightly keeps. Check the converted steps instead: every depends_on must
name a step that is in the pipeline. Also trim comments: drop the
reference to test-template-amd.j2, drop the retry note, and say why
image-build-amd's depends_on is rebuilt as it is.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
- apply_aiter_nightly's docstring says where the overlay goes and what
  it rewires.
- The root README's AITER_NIGHTLY row points to the AITER nightly
  section instead of repeating it.
- Tests: check zen5 by its real device value, use AMD_NATIVE_BASE_IMAGE,
  compare the whole input in the no-mutation test, share the generate()
  setup, rename the overlay settings test, drop a test generate()
  already covers, and import global_config at the top.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
- apply_aiter_nightly swaps in the new image-build-amd and appends the
  overlay; list order does not matter, as group_steps sorts by label.
- Drop the duplicate-key guard: Buildkite rejects a duplicate key at
  upload anyway.
- Drop the comment on the AITER nightly check in _step_should_run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
…ies_exist

It checks nothing AITER-specific: every depends_on must name a step in
the pipeline. It still runs only in the AITER nightly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Whoever sets AITER_NIGHTLY=1 already knows which jobs it runs. Keep
annotations for things that need attention: errors, and the overlay's
own note on the wheel it installed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
…s_on

image-build-amd keeps its depends_on and adds aiter-nightly-amd. The
overlay already depends on ensure-ci-base-amd, so the order is unchanged.
Reword the comment on the ci_base handoff to say why it is there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
- Write the AITER nightly filters as "runs in the nightly, or this is
  not the nightly".
- Drop "(native or DinD)" from the runs_in_aiter_nightly docstring.
- README: drop the DOCS_ONLY_DISABLE note, which the AITER_NIGHTLY entry
  already covers, and reword the VLLM_CI_ONLY_STEP_KEYS sentence on
  requesting a step the nightly does not run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Match the bootstrap timeout.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
josh-schell-amd and others added 5 commits November 2, 2026 12:33
Fold the check_dependencies_exist test into the generate() test by
matching the full "amd-needs-cuda -> cuda-only" message there, and drop
the trivial does-not-mutate-input test.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
vllm-project/vllm#61939 moved the ROCm build to build.sh: image-build-amd
installs the AITER nightly wheel itself (AITER_NIGHTLY / AITER_SPEC, in the
uncached per-commit test stage), and ci-infra#820 already sends that build
to rocm/vllm-dev. The ensure-ci-base-amd step and aiter-nightly-overlay.sh
the overlay depended on no longer exist, so with AITER_NIGHTLY=1 generation
failed on every vLLM main checkout.

Drop the overlay step, the ci_base metadata swap and the cache-branch env;
keep vLLM's build steps as they are. Fail generation on a checkout without
build.sh rather than silently test the stock AITER. The step selection
(AMD build steps and gfx942/gfx950 jobs only, unblocked) is unchanged.

Tests now use vLLM's amd.yaml build steps, and cover the rocm/vllm-dev
repo and pod image, the early image upload (only the AMD image steps go
up early), and the missing-build.sh error.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
The dependency check ran on the converted pipeline, after
upload_image_steps_early had already put refresh-rocm-base-amd and
image-build-amd into the build. A kept job depending on a dropped step
failed generation, but left both image steps running with no tests after
them. The TORCH_NIGHTLY conflict raised in init_global_config, without an
error annotation.

Check every AITER nightly error in generate() before anything is
uploaded, each with an error annotation. The dependency check now works
on the step list: aiter_nightly_jobs() gives the jobs the nightly uploads
with their depends_on as the converter emits them (a test pins the two
together), and the retry-key check uses the same set. This drops
check_dependencies_exist and its unreachable str branch.

The flag-off test now pins the full job set.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
- Retry builds expand an AMD GPU job's prerequisites as the converter
  emits its depends_on (normalize_amd_depends_on). A native job whose raw
  depends_on named image-build (e.g. a group default) was retried without
  image-build-amd and refresh-rocm-base-amd, and uploaded waiting on a
  step not in the build. The same bug is on main for any retry build; the
  rendered real vLLM pipeline is unchanged with the flag off.
- aiter_nightly_jobs no longer predicts an amd- mirror for a step that is
  itself an AMD GPU job: the converter never emits one, so a dependency on
  it passed the check and dangled, and a retry naming it was accepted.
- Fail generation, before any upload, when a test-selector recorder
  (VLLM_CI_KERNREC, VLLM_CI_KERNREC_AMD, VLLM_CI_FNREC) is armed: an
  AMD-only run on an unreleased AITER would skew its records.
- The selector decision record lists only the nightly's jobs as
  legacy/scheduled, not every step in the tree.
- Docs: the selector skips the AITER nightly; on a PR build pre-commit
  still gates the AMD jobs.

New tests, each failing before its fix where there is one: odd step
shapes against the converter (unkeyed, A100 mirror, dind mirror, mirror
without a device, native step with a mirror, inherited image-build),
runtime sharding plans only kept jobs, retry builds through generate()
(kept and dropped keys), no "Run more jobs" step, the selector record,
the recorder errors, and AITER_NIGHTLY values other than "1".

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
josh-schell-amd and others added 3 commits November 3, 2026 14:20
The AITER nightly is now a build of named steps, as a retry build
(VLLM_CI_ONLY_STEP_KEYS) is: aiter_nightly_step_keys() names the AMD build
steps and the gfx942/gfx950 GPU jobs (or checks a retry build's keys), and
the existing only_step_keys path does the rest. That removes the nightly
filters from the converter, the separate dependency predictor, the
retry-key check in select_steps_and_dependencies and the selector-record
filter: one check (selected - nightly steps) covers both a dropped
dependency and a retry of a dropped step. Like any named-steps build it
skips the early image upload, so nothing goes up before the checks pass.

The docs-only exemption moves from global_config into generate()'s
docs-only condition, next to the other exemptions; global_config only
reads AITER_NIGHTLY.

The tests go from 600 to under 300 lines: one step list with every shape,
one end-to-end nightly run, a flag-off run, a retry build, and one
parametrized failure test. Each guard was mutation-checked: removing it
fails a test.

On the real vLLM pipeline the nightly's output is unchanged (210 jobs),
and the flag-off output still matches main in 9 variants.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
Its AMD-only runs on an unreleased AITER would mislead the test selector's records. The recorder switches now read as off on the nightly, so a recorder variable carried over from another schedule costs nothing instead of failing the build.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: josh schell <josh.schell@amd.com>
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.

2 participants