Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions templates/assembly-root/project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,14 @@ topic: {{TOPIC}}
# `private`, `public` or `internal` (an enterprise org-internal repository).
# NOT ENFORCED HERE — GitHub is the source of truth for what a repository's
# visibility actually is — but recording it is what lets a reader tell,
# without three `gh repo view` calls, why the legs are internal. For a
# scaffolded project this is all three repositories' visibility; for an
# without three `gh repo view` calls, why the legs it created are internal.
# It is the visibility the run that created this file ASKED FOR, which is not
# always what a repository is: for a scaffold, `--visibility` where one was
# given; where none was, the visibility GitHub gave, before the plan, of an
# existing assembly root the run reuses; and otherwise `private`, a root
# whose read failed included. A repository the run REUSES keeps the
# visibility it already has — the run changes no repository's visibility —
# so this can differ from what GitHub says of one of the three. For an
# in-place adoption it is the value the two NEW legs were created with — the
# assembly root IS the adopted source and keeps whatever visibility it
# already had on GitHub, unchanged by this tool.
Expand Down
8 changes: 7 additions & 1 deletion templates/family-root/family.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ created_on: "{{CREATED_ON}}"

# `private`, `public` or `internal`. NOT ENFORCED HERE — GitHub is the source
# of truth for what a repository's visibility actually is — but recording it
# is what lets a reader tell why the members need a credential in CI.
# is what lets a reader tell why the members need a credential in CI. It is
# the visibility the `family.py init` run that wrote this file ASKED FOR, not
# a reading of any repository: `--visibility`, which is `private` unless the
# run was given another. It is the HOLDER's alone, since each member has its
# own, and a holder the run REUSES keeps the visibility it already has — the
# run changes no repository's visibility — so this can differ from what
# GitHub says of the holder.
visibility: "{{VISIBILITY}}"

# The HOLDER's own branch: the one a new holder is created on, and the one
Expand Down
119 changes: 119 additions & 0 deletions tests/test_visibility_field_words.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# SPDX-License-Identifier: Apache-2.0
"""What the comment above `visibility:` says the field records (#913, U039).

`templates/assembly-root/project.yaml` said "For a scaffolded project this is
all three repositories' visibility". It is not wherever a repository was
reused: the run records the visibility IT asked for, which is not always what
a repository is, in an order `_leg_visibility` follows (`--visibility` where
one was given; where none was, the reused root's own, as GitHub gave it before
the plan; otherwise `private`), and a repository it reuses keeps the
visibility it has, because no run changes one. `family.yaml` is the same for
the holder, with no root to inherit from: a reused PUBLIC holder under the
default `--visibility private` records `private`, as
`test_free_plan_hint_reads.py` holds.

Brett Heap ruled on 2026-10-21T10:39:44Z that the WORDS change and no code
does ("U039 and U037: take your recommendations"): `visibility:` is "the
visibility this run asked for". The behaviour the words describe is pinned
where it is run, by `test_reuse_visibility.py` (the reused root's own is
inherited, and an explicit `--visibility` wins) and by
`test_free_plan_hint_reads.py` (a family keeps the run's); this file pins the
words, which no test did. The comments are copied into every project and
family this tool makes, so a word that goes back says again what a reused
repository does not do.

NO NETWORK, NO GITHUB, NO PROCESS: the two templates, read as text.
"""

from __future__ import annotations

import pytest

from conftest import REPO

ASSEMBLY = REPO / "templates" / "assembly-root" / "project.yaml"
FAMILY = REPO / "templates" / "family-root" / "family.yaml"
BOTH = pytest.mark.parametrize("path", [ASSEMBLY, FAMILY],
ids=["project.yaml", "family.yaml"])

#: The line the comment sits on.
FIELD = 'visibility: "{{VISIBILITY}}"'


def comment_above_visibility(path) -> str:
"""The comment block directly above `visibility:`, its `#` and its line
breaks gone, so a phrase is found whichever line it was wrapped on."""
lines = path.read_text(encoding="utf-8").splitlines()
at = lines.index(FIELD)
block: list[str] = []
for line in reversed(lines[:at]):
if not line.startswith("#"):
break
block.append(line.lstrip("#").strip())
return " ".join(reversed(block))


@BOTH
def test_visibility_is_what_the_run_asked_for(path):
"""The key claim of #913's ruling, in both manifests: what is recorded
is what the run was asked for, and a reused repository keeps its own,
which no run changes."""
comment = comment_above_visibility(path)
for phrase in ("ASKED FOR", "`--visibility`", "`private`",
"REUSES keeps the visibility it already has",
"changes no repository's visibility"):
assert phrase in comment, (phrase, comment)


@BOTH
def test_visibility_is_not_called_the_repositories_visibility(path):
"""The sentence the ruling replaced, in the words it used."""
comment = comment_above_visibility(path)
assert "this is all three repositories' visibility" not in comment
assert "all three repositories" not in comment, comment


@BOTH
def test_github_is_still_the_source_of_truth(path):
comment = comment_above_visibility(path)
assert "NOT ENFORCED HERE" in comment, comment
assert "GitHub is the source of truth" in comment, comment


def test_the_scaffold_comment_says_what_is_recorded_in_the_order_it_is():
"""`_leg_visibility`'s order, in the words of the comment: `--visibility`
where one was given, which wins over a reused root; where none was, the
visibility GitHub gave, before the plan, of an existing assembly root the
run reuses; and otherwise `private`. Where the root is the answer the
field IS a reading of a repository, so the comment must not say it is
never one."""
comment = comment_above_visibility(ASSEMBLY)
order = ("for a scaffold, `--visibility` where one was given; where none "
"was, the visibility GitHub gave, before the plan, of an "
"existing assembly root the run reuses; and otherwise "
"`private`")
assert order in comment, comment
assert "not a reading of any repository" not in comment, comment
assert "which is not always what a repository is" in comment, comment
assert "why the legs it created are internal" in comment, comment


def test_the_in_place_adoption_sentence_holds():
"""Adoption creates the two legs at `plan --visibility` and keeps the
source's root as it is, which is what the sentence says and the ruling
left standing."""
comment = comment_above_visibility(ASSEMBLY)
for phrase in ("in-place adoption it is the value the two NEW legs were "
"created with",
"keeps whatever visibility it already had on GitHub, "
"unchanged by this tool"):
assert phrase in comment, (phrase, comment)


def test_the_family_comment_says_it_is_the_holders_alone():
"""`family.yaml` records the HOLDER's, as `family.py init` fills it from
`--visibility`; a member is a project, with a `visibility:` of its own."""
comment = comment_above_visibility(FAMILY)
assert "not a reading of any repository" in comment, comment
assert "It is the HOLDER's alone" in comment, comment
assert "a holder the run REUSES keeps" in comment, comment
Loading