Skip to content

Run a smaller subset of targets on pull requests by default#1075

Open
zanieb wants to merge 6 commits intomainfrom
zb/subset-pr
Open

Run a smaller subset of targets on pull requests by default#1075
zanieb wants to merge 6 commits intomainfrom
zb/subset-pr

Conversation

@zanieb
Copy link
Copy Markdown
Member

@zanieb zanieb commented Apr 1, 2026

Currently, pull requests run all targets by default and labels can be used to select a subset of the matrix. However, CI is quite expensive and it's very rare to need to test the whole matrix, so the default is a bit backwards.

In this change, we update pull requests to run on a subset of targets by default: Python 3.14 on macOS, Linux, and Windows with the most popular architecture. We include both glibc and musl variants of Linux. We include armv7 as an arbitrary cross-compile case — I'd be happy to take suggestions on an alternative there.

This breaks our labeling concept a bit, as our labels currently do pure subsetting of the matrix. The labels will continue to subset, but with some nuances:

  • Applying a label will generally subset the default selection, e.g., platform:linux will only run the Linux subset of the defaults described above.
  • Labels that would null the default subset, e.g., python:3.12 or build:debug, will instead change the default set to target that variant.
  • There are new platform:all, python:all, arch:all, libc:all, and build:all labels that can be used to expand the targets.

@zanieb zanieb added ci:dry-run platform:all Select all platforms, e.g., darwin, linux, windows python:all Select all Python versions arch:all Select all architectures labels Apr 1, 2026
@zanieb zanieb added platform:darwin Specific to the macOS platform and removed platform:all Select all platforms, e.g., darwin, linux, windows labels Apr 1, 2026
@zanieb zanieb added build:all platform:linux Specific to the Linux platform and removed platform:darwin Specific to the macOS platform labels Apr 1, 2026
@zanieb zanieb force-pushed the zb/subset-pr branch 2 times, most recently from 44eec28 to b386b4a Compare April 1, 2026 14:30
@zanieb zanieb added build:debug and removed platform:linux Specific to the Linux platform python:all Select all Python versions arch:all Select all architectures build:all labels Apr 1, 2026
ci-matrix.py Outdated
Comment on lines +607 to +612
directives = labels.get("directives", set())
python_entries = generate_python_build_matrix_entries(
config,
runners,
args.platform,
labels,
{"directives": directives} if directives else None,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This pattern is really weird?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't follow why this line is changing. Passing through labels seems like it would work fine?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I fixed this already

@zanieb zanieb marked this pull request as ready for review April 1, 2026 16:16
Copy link
Copy Markdown
Collaborator

@geofft geofft left a comment

Choose a reason for hiding this comment

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

This seems pretty complicated and I'm not sure that I understand exactly what the logic is and a mental model of which builds will run in response to which targets. To be fair I don't feel like I have a 100% grasp of the current logic, and we could decide that we have few enough existing users that backwards compatibility is not a goal. But it feels like it should be possible to do this task with fewer lines of code and more readably.

I'm okay with deciding that we don't want to put time into that, and we can always have an LLM make further big changes if we don't like the behavior.

ci-matrix.py Outdated
Comment on lines +607 to +612
directives = labels.get("directives", set())
python_entries = generate_python_build_matrix_entries(
config,
runners,
args.platform,
labels,
{"directives": directives} if directives else None,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't follow why this line is changing. Passing through labels seems like it would work fine?

ci-matrix.py Outdated
return False
def get_all_build_options(ci_config: dict[str, Any], target_triple: str) -> list[str]:
"""Get all build options (including conditional) for a target from ci-targets.yaml."""
for _platform, platform_config in ci_config.items():
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
for _platform, platform_config in ci_config.items():
for platform_config in ci_config.values():

ci-matrix.py Outdated
Comment on lines +171 to +180
if expand_platform or expand_arch or expand_libc:
source_triples = {}
for platform, platform_config in ci_config.items():
for triple, config in platform_config.items():
source_triples[triple] = (platform, config)
else:
source_triples = {}
for triple in pr_config["targets"]:
platform = find_target_platform(ci_config, triple)
source_triples[triple] = (platform, ci_config[platform][triple])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This logic is a little bit complicated for me to make sense of. I think that if we unconditionally do the if-case logic (set source_triples to every possible triple in ci-targets.yaml, without filtering by pr-targets.yaml), and remove the if expand_platform or expand_arch or expand_libc: on line 187 and unconditionally run the matches_default_pattern filter, the outcome will be the same. Is that correct?

ci-matrix.py Outdated
if version in ci_target_config["python_versions"]
]
else:
python_versions = [pr_default_version]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Seems erroneous for pr_default_version to apply if it's not listed in ci_target_config.

I see there's a validation step later but I think that if you use arch:all or whatever to bring in platforms that aren't in the default set, and they don't support the default Python version, the validation won't notice that.

ci-matrix.py Outdated
Comment on lines +232 to +238
for option in sorted(build_filters)
if option in all_build_options
]
build_options_conditional = []
else:
build_options = get_default_build_options(ci_config, pr_config, triple)
build_options_conditional = []
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comments here.

ci-matrix.py Outdated
Comment on lines +567 to +576
with open(CI_DEFAULTS_YAML) as f:
ci_defaults = yaml.safe_load(f)

pull_request_defaults = ci_defaults.get("pull_request")
if pull_request_defaults is None:
print(
f"error: {CI_DEFAULTS_YAML} is missing a pull_request section",
file=sys.stderr,
)
sys.exit(1)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It seems like this should just be unconditionally loaded and we can do ci_defaults.get(args.event)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

(and not error if there's not a section for the event type, since that just means... use everything)

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.

3 participants