Skip to content

Commit c461a2c

Browse files
authored
Merge pull request #624 from posit-dev/dev-spec-channel-filter
Filter ci matrix by dev-spec channel
2 parents eca9265 + 7b7c3bb commit c461a2c

2 files changed

Lines changed: 78 additions & 1 deletion

File tree

posit-bakery/posit_bakery/cli/ci.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ def matrix(
135135
c = BakeryConfig.from_context(context=context, settings=settings)
136136
images = [i for i in c.model.images if image_name is None or re.search(image_name, i.name) is not None]
137137

138+
# A --dev-spec carrying a channel implies the matrix should be filtered to that
139+
# channel. The shared CI workflow folds the dispatched channel into the dev-spec
140+
# and stops passing --dev-channel, so without this the other channels' dev versions
141+
# would still be emitted (only the matching one gets its version pinned).
142+
effective_dev_channel = settings.dev_channel
143+
if effective_dev_channel is None and settings.dev_spec is not None:
144+
effective_dev_channel = settings.dev_spec.channel
145+
138146
data = []
139147
for img in images:
140148
entry = {"image": img.name}
@@ -153,7 +161,7 @@ def matrix(
153161
# If EXCLUDE: fall through using img.versions (devVersions are appended
154162
# there by load_dev_versions). The dev_versions filter below handles the rest.
155163
for ver in versions:
156-
included, _ = ver.matches_dev_filter(dev_versions, dev_channel)
164+
included, _ = ver.matches_dev_filter(dev_versions, effective_dev_channel)
157165
if not included:
158166
continue
159167
if image_version is not None and not version_matches(ver.name, image_version):

posit-bakery/test/cli/test_ci_matrix_dev_versions.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,72 @@ def test_prod_versions_excluded(self, mock_config_with_matrix_dev_image):
171171
versions_in_output = {e["version"] for e in data}
172172
assert prod_ver1.name not in versions_in_output
173173
assert prod_ver2.name not in versions_in_output
174+
175+
176+
@pytest.fixture
177+
def mock_config_with_two_channel_dev_image():
178+
"""Patch BakeryConfig to return one non-matrix image carrying both a
179+
daily and a preview dev version (the workbench/session-init shape)."""
180+
daily = _make_version("2026.99.0+237", is_dev=True, channel=ReleaseChannelEnum.DAILY)
181+
preview = _make_version("2026.99.0+240", is_dev=True, channel=ReleaseChannelEnum.PREVIEW)
182+
img = MagicMock()
183+
img.name = "workbench"
184+
img.matrix = None
185+
img.versions = [daily, preview]
186+
187+
with patch("posit_bakery.cli.ci.BakeryConfig") as mock:
188+
instance = MagicMock()
189+
instance.model.images = [img]
190+
mock.from_context.return_value = instance
191+
yield mock, daily, preview
192+
193+
194+
class TestCiMatrixDevSpecChannelFilter:
195+
"""A --dev-spec carrying a channel filters the matrix to that channel even
196+
when --dev-channel is omitted. The shared workflow folds the channel into
197+
the dev-spec and drops --dev-channel, so the matrix must honor it."""
198+
199+
def test_filters_to_dev_spec_channel(self, mock_config_with_two_channel_dev_image):
200+
_, daily, preview = mock_config_with_two_channel_dev_image
201+
result = runner.invoke(
202+
app,
203+
[
204+
"ci",
205+
"matrix",
206+
"--context",
207+
BASIC_CONTEXT,
208+
"--dev-versions",
209+
"only",
210+
"--dev-spec",
211+
'{"version": "2026.99.0+240", "channel": "preview"}',
212+
],
213+
catch_exceptions=False,
214+
)
215+
assert result.exit_code == 0, result.output
216+
data = json.loads(result.stdout.strip())
217+
versions = {e["version"] for e in data}
218+
assert preview.name in versions
219+
assert daily.name not in versions
220+
221+
def test_branch_only_dev_spec_does_not_filter(self, mock_config_with_two_channel_dev_image):
222+
"""A branch-only dev-spec carries no channel, so all channels stay in the matrix."""
223+
_, daily, preview = mock_config_with_two_channel_dev_image
224+
result = runner.invoke(
225+
app,
226+
[
227+
"ci",
228+
"matrix",
229+
"--context",
230+
BASIC_CONTEXT,
231+
"--dev-versions",
232+
"only",
233+
"--dev-spec",
234+
'{"release_branch": "2026.06"}',
235+
],
236+
catch_exceptions=False,
237+
)
238+
assert result.exit_code == 0, result.output
239+
data = json.loads(result.stdout.strip())
240+
versions = {e["version"] for e in data}
241+
assert preview.name in versions
242+
assert daily.name in versions

0 commit comments

Comments
 (0)