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
2 changes: 0 additions & 2 deletions docs/site/src/content/docs/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ Documentation updates for the v0.21.0 beta-32 release:
reviewed release-image definitions under `release/docker/`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split the change along owning-area boundaries

This commit changes both release/ and docs/site/, while the root AGENTS.md requires each change to remain scoped to one owning area. Move the public changelog edit into a separate docs-site change from the release tooling, manifest, and release-note corrections.

AGENTS.md reference: AGENTS.md:L280-L282

Useful? React with 👍 / 👎.

- Documented operator-mounted configuration, governed packages, secrets,
keys, and audit storage for all three runtime images.
- Documented that the Relay installer verifies and installs matching `relay`
and `relayctl` binaries together on Linux amd64.
- Added the v0.21.0 candidate documentation archive.

## 2026-08-12
Expand Down
2 changes: 1 addition & 1 deletion release/manifests/registry-stack-beta-32.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ artifacts:

identifier_catalog:
path: products/identifiers/generated/catalog.v1.json
sha256: 7a8130406862922a1c52f81a43577446713ab10ffe76b49179946ad861af3ac9
sha256: f5523ec180e3c3d18f7f18a1704d3932e84a66f03ead0e9124d3c6d366aa20f0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the required DCO sign-off

The reviewed commit has no Signed-off-by trailer, although the repository's root AGENTS.md requires every commit to carry a DCO sign-off. Recreate this commit with git commit -s before merging so it satisfies the repository's contribution policy.

AGENTS.md reference: AGENTS.md:L272-L275

Useful? React with 👍 / 👎.

entry_count: 47

external: {}
3 changes: 0 additions & 3 deletions release/notes/v0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ Python, and Node.
- Relay reads the operator-mounted runtime configuration selected by its
`--runtime` argument, which defaults in the image to
`/etc/relay/runtime.yaml`.
- The Relay installer downloads, verifies, and installs the matching `relay`
and `relayctl` binaries together on Linux amd64. If either asset cannot be
verified or installed, the installer preserves the previous pair.
- The repository's top-level `docker/` definitions remain local source-build
images. Official release images use the reviewed definitions under
`release/docker/`.
Expand Down
19 changes: 18 additions & 1 deletion release/scripts/registry-release
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,20 @@ def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()


def local_tag_target(repo: Path, tag: str) -> str | None:
resolved = subprocess.run(
["git", "rev-parse", "--verify", f"refs/tags/{tag}^{{}}"],
cwd=repo,
text=True,
capture_output=True,
check=False,
)
target = resolved.stdout.strip()
if resolved.returncode == 0 and HEX40.fullmatch(target):
return target
return None


def validate(manifest_path: Path) -> int:
manifest = load_yaml(manifest_path)
errors: list[str] = []
Expand Down Expand Up @@ -318,12 +332,15 @@ def validate(manifest_path: Path) -> int:
if repository.returncode == 0 and repository.stdout.strip()
else ROOT
)
catalog_source_ref = source_ref if has_source_ref else None
if catalog_source_ref is None:
catalog_source_ref = local_tag_target(repo_root, source_tag)
Comment on lines +336 to +337

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle missing release tags before using current catalog bytes

In a shallow or tagless checkout, local_tag_target() returns None, so this path silently validates the historical v0.21.0 manifest against the current working-tree catalog. The corrected beta-32 manifest records digest f5523e…, while the current catalog is 7a8130…, causing both registry-release validate and the newly added copied-manifest test to fail when v0.21.0 is unavailable; the full-history CI checkout masks this non-hermetic behavior. Resolve the immutable source independently of ambient tags, or report the missing tag explicitly instead of falling back to current bytes.

AGENTS.md reference: AGENTS.md:L261-L268

Useful? React with 👍 / 👎.

errors.extend(
identifier_catalog_errors(
version,
identifier_catalog,
repo_root,
source_ref if has_source_ref else None,
catalog_source_ref,
)
)
for name, artifact_version in sorted(artifacts.items()):
Expand Down
73 changes: 70 additions & 3 deletions release/scripts/test_registry_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -1411,8 +1411,8 @@ def test_validate_current_selects_highest_semver_manifest(self) -> None:
manifest_dir.mkdir()
source_ref = git(ROOT, "rev-parse", "HEAD")
for version, release_id in (
("0.19.0", "beta-29"),
("0.20.0", "beta-30"),
("0.91.0", "beta-29"),
("0.92.0", "beta-30"),
):
manifest = write_manifest(
manifest_dir,
Expand All @@ -1435,7 +1435,7 @@ def test_validate_current_selects_highest_semver_manifest(self) -> None:
)

self.assertEqual(0, result.returncode, result.stderr)
self.assertIn("beta-30 0.20.0", result.stdout)
self.assertIn("beta-30 0.92.0", result.stdout)
self.assertNotIn("beta-29", result.stdout)

def test_validate_current_requires_a_release_manifest(self) -> None:
Expand Down Expand Up @@ -1625,6 +1625,73 @@ def test_validate_uses_identifier_catalog_from_recorded_source_ref(self) -> None
self.assertNotEqual(0, mismatched.returncode)
self.assertIn("does not match the committed catalog bytes", mismatched.stderr)

def test_validate_uses_identifier_catalog_from_existing_source_tag(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = init_repo(Path(tmp))
catalog_path = root / "products/identifiers/generated/catalog.v1.json"
catalog_path.parent.mkdir(parents=True)
catalog_path.write_text(
json.dumps({"version": 1, "entries": [{"status": "active"}]})
+ "\n",
encoding="utf-8",
)
git(root, "add", str(catalog_path.relative_to(root)))
git(root, "commit", "-m", "record tagged catalog")
tagged_source = git(root, "rev-parse", "HEAD")
git(root, "tag", "v0.19.1")
manifest = write_manifest(
root,
version="0.19.1",
source_ref=tagged_source,
)
data = yaml.safe_load(manifest.read_text(encoding="utf-8"))
del data["stack"]["source_ref"]
del data["stack"]["status"]
manifest.write_text(
yaml.safe_dump(data, sort_keys=False), encoding="utf-8"
)

catalog_path.write_text(
json.dumps(
{
"version": 1,
"entries": [
{"status": "active"},
{"status": "active"},
],
}
)
+ "\n",
encoding="utf-8",
)
git(root, "add", str(catalog_path.relative_to(root)))
git(root, "commit", "-m", "advance current catalog")
accepted = run_tool("validate", str(manifest))

data = yaml.safe_load(manifest.read_text(encoding="utf-8"))
data["identifier_catalog"]["sha256"] = hashlib.sha256(
catalog_path.read_bytes()
).hexdigest()
data["identifier_catalog"]["entry_count"] = 2
manifest.write_text(
yaml.safe_dump(data, sort_keys=False), encoding="utf-8"
)
mismatched = run_tool("validate", str(manifest))

self.assertEqual(0, accepted.returncode, accepted.stderr)
self.assertNotEqual(0, mismatched.returncode)
self.assertIn("does not match the committed catalog bytes", mismatched.stderr)

def test_validate_copied_manifest_uses_tool_repository_source_tag(self) -> None:
source = ROOT / "release/manifests/registry-stack-beta-32.yaml"
with tempfile.TemporaryDirectory() as tmp:
copied = Path(tmp) / source.name
copied.write_bytes(source.read_bytes())
result = run_tool("validate", str(copied))

self.assertEqual(0, result.returncode, result.stderr)
self.assertIn("validated", result.stdout)

def test_relay_installer_joins_the_exact_inventory_after_v0_19_0(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
Expand Down