fix(context): accept RepositoryEntry object form in .project/ reader (closes #385) - #386
Merged
mlieberman85 merged 1 commit intoAug 23, 2026
Conversation
…loses darnitdevorg#385) CNCF `.project/` types.go changed `Project.Repositories` from `[]string` to `[]RepositoryEntry` in cncf/automation@bd7fec94 (2026-08-21, "feat: add RepositoryEntry type with tags and primary fields"). Each `repositories[*]` item may now be either a plain string OR an object of shape `{url, tags?, primary?}`. Feature 030's nightly canary correctly fired on the drift; without a reader reconcile, a `.project/project.yaml` written in the new object form degrades silently (the pre-fix reader treats each dict item as a whole-value string that no downstream consumer knows how to use). Mirroring feature 030's collapse-to-scalar pattern for the `StringOrSlice` reshape, add `_coerce_repository_entry(value) -> str` that returns the input for a scalar string, `value['url']` for a mapping, and `""` for anything else. Reader now maps every item through the coercer and filters out empty results so a malformed entry (missing `url`) does not silently expand into a stringified representation of the mapping. `ProjectConfig.repositories` stays `list[str]`; downstream consumers (`dot_project_merger.py`, `dot_project_mapper.py`) are unchanged. `tags` and `primary` metadata is dropped at parse time. If a future control needs the metadata, we can promote the field to a structured RepositoryEntry dataclass in a later reconcile without a further reshape. Per feature 030 Q3: bump DOT_PROJECT_SPEC_VERSION 1.2.0 -> 1.3.0 in lock-step with the tracked-hash file (860df23... -> afa3d179...). Module docstring's reconciliation history is extended. Tests: - `TestRepositoryEntryReshape` (6 tests): scalar-only, object-only, mixed, malformed-object dropped, empty list, spec-version bump. - `test_upstream_spec_unchanged` passes on the new hash. - Full workspace: 2748 pass, 17 skip, 0 fail. Side note recorded in darnitdevorg#385: `tests/darnit/parity/tier1/conftest.py`'s `pytest_collection_modifyitems` applies `integration` to every collected item (not scoped to tier1/), which is why unrelated PRs (darnitdevorg#384) are gated on the upstream canary. Worth constraining the hook to items under its own conftest scope; out of scope here.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
CNCF
.project/types.go changedProject.Repositoriesfrom[]stringto[]RepositoryEntryin cncf/automation@bd7fec94 (2026-08-21, "feat: add RepositoryEntry type with tags and primary fields"). Eachrepositories[*]item may now be either a plain string OR an object of shape{url, tags?, primary?}. Feature 030's nightly canary (test_upstream_spec_unchanged) correctly fired on the drift. Without a reader reconcile, a.project/project.yamlwritten in the new object form degrades silently -- the pre-fix reader stores each dict item verbatim so no downstream consumer can extract the URL.Mirrors feature 030's
_coerce_scalar_or_listcollapse pattern:_coerce_repository_entry(value) -> str: returns the input for a scalar string,value['url']for a mapping, and\"\"for anything else.url) does not silently expand into a stringified representation of the mapping.ProjectConfig.repositoriesstayslist[str]. Downstream consumers (dot_project_merger.py,dot_project_mapper.py) are unchanged.tagsandprimarymetadata is dropped at parse time. If a future control needs the metadata, we can promote the field to a structuredRepositoryEntrydataclass in a later reconcile without a further reshape.Per feature 030 Q3: bumps
DOT_PROJECT_SPEC_VERSION1.2.0 -> 1.3.0 in lock-step with the tracked-hash file (860df23...->afa3d179...). Module docstring's reconciliation history is extended.Closes #385.
Side note captured in #385
tests/darnit/parity/tier1/conftest.py:32'spytest_collection_modifyitemsapplies theintegrationmarker to every collected item (not scoped to tier1/), which is why unrelated PRs (e.g., #384) got gated on this upstream canary. Worth constraining that hook to items under its own conftest scope; out of scope for this PR but tracked.Test plan
pytest tests/darnit/context/test_dot_project.py::TestRepositoryEntryReshape-- 6 new tests pass (scalar-only, object-only, mixed, malformed-object dropped, empty-list, spec-version bump).pytest tests/darnit/context/test_dot_project_upstream.py-- all 5 pass on the new hash (canary now green).pytest tests/-- 2748 pass, 17 skip, 0 fail. No deselect needed.ruff checkon touched files -- clean.python scripts/validate_sync.py --verbose-- PASS.Backward compatibility: additive. Existing
.project/project.yamlfiles with plain-stringrepositoriesitems still parse to the samelist[str]shape. New object-form files now also parse correctly. No downstream consumer's contract changes.