Add successful ReleaseKit publication fixture

This commit is contained in:
2026-10-08 16:33:43 +00:00
parent d5940856be
commit 51b072965c
2 changed files with 358 additions and 2 deletions

View File

@@ -7,8 +7,9 @@ owns the implementation steps; the roadmap owns purpose and selected policy.
Status: Stage 1's tool selection and dependency preparation are complete in
`3ca01ae`. The agreed series-based Go minimum supersedes the original patch-based
requirement. Stage 2's example checker and shared validation profile are
complete in `0d163f8`. Stage 3's native tool bootstrap is complete. Resume
adoption at Stage 4 after this revision.
complete in `0d163f8`. Stage 3's native tool bootstrap is complete in
`d594085`. Stage 4's successful-publication fixture is complete. Resume
adoption at Stage 5 after this revision.
## Baseline And Working Rules

355
scripts/test-release.py Normal file
View File

@@ -0,0 +1,355 @@
"""Exercise successful ReleaseKit publication wiring in a disposable repository."""
import json
import os
import shutil
import subprocess
import sys
import tempfile
import textwrap
from pathlib import Path
REPOSITORY_ROOT = Path(__file__).resolve().parent.parent
RELEASE_VERSION = "v0.0.1"
RELEASEKIT_MODULE = "gitea.maximumdirect.net/eric/ReleaseKit"
def run(command, cwd, environment):
try:
result = subprocess.run(
command,
cwd=cwd,
env=environment,
text=True,
capture_output=True,
check=False,
)
except OSError as error:
raise RuntimeError(f"could not run {command[0]}: {error}") from error
if result.returncode != 0:
details = [
f"command failed with status {result.returncode}: {' '.join(command)}"
]
if result.stdout:
details.append(f"stdout:\n{result.stdout.rstrip()}")
if result.stderr:
details.append(f"stderr:\n{result.stderr.rstrip()}")
raise RuntimeError("\n".join(details))
return result.stdout
def write_file(path, contents):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(textwrap.dedent(contents).lstrip("\n"), encoding="utf-8")
def repo_git(repository, environment, *arguments):
return run(
["git", "-C", str(repository), *arguments],
cwd=repository.parent,
environment=environment,
)
def remote_git(remote, temporary_root, environment, *arguments):
return run(
["git", "--git-dir", str(remote), *arguments],
cwd=temporary_root,
environment=environment,
)
def fixture_sources(repository, environment):
write_file(
repository / "fixture.go",
"""
package fixture
func candidateValue() string { return "ready" }
""",
)
write_file(
repository / "fixture_test.go",
f"""
package fixture
import (
"encoding/json"
"os"
"runtime"
"testing"
)
func TestCandidateSuite(t *testing.T) {{
if candidateValue() != "ready" {{
t.Fatal("candidate package is not ready")
}}
marker := os.Getenv("FIXTURE_SUITE_MARKER")
if marker == "" {{
t.Fatal("FIXTURE_SUITE_MARKER is not set")
}}
record := struct {{
GoVersion string `json:"go_version"`
Race bool `json:"race"`
}}{{GoVersion: runtime.Version(), Race: raceDetectorEnabled}}
data, err := json.Marshal(record)
if err != nil {{
t.Fatal(err)
}}
file, err := os.OpenFile(marker, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {{
t.Fatal(err)
}}
if _, err := file.Write(append(data, '\\n')); err != nil {{
file.Close()
t.Fatal(err)
}}
if err := file.Close(); err != nil {{
t.Fatal(err)
}}
}}
""",
)
write_file(
repository / "race_enabled_test.go",
"""
//go:build race
package fixture
const raceDetectorEnabled = true
""",
)
write_file(
repository / "race_disabled_test.go",
"""
//go:build !race
package fixture
const raceDetectorEnabled = false
""",
)
go_files = [
str(repository / filename)
for filename in (
"fixture.go",
"fixture_test.go",
"race_enabled_test.go",
"race_disabled_test.go",
)
]
run(["gofmt", "-w", *go_files], cwd=repository, environment=environment)
def prepare_repository(repository, remote, environment, module_bytes):
run(
["git", "init", "--bare", "--initial-branch=main", str(remote)],
cwd=repository.parent,
environment=environment,
)
run(
["git", "init", "--initial-branch=main", str(repository)],
cwd=repository.parent,
environment=environment,
)
repo_git(repository, environment, "config", "user.name", "ReleaseKit Fixture")
repo_git(repository, environment, "config", "user.email", "fixture@example.invalid")
repo_git(repository, environment, "remote", "add", "origin", str(remote))
for name, contents in module_bytes.items():
(repository / name).write_bytes(contents)
write_file(
repository / ".gitignore",
"""
.releasekit/
""",
)
write_file(
repository / "releasekit.json",
(REPOSITORY_ROOT / "releasekit.json").read_text(encoding="utf-8"),
)
scripts = repository / "scripts"
scripts.mkdir(parents=True, exist_ok=True)
shutil.copy2(REPOSITORY_ROOT / "scripts/releasekit.sh", scripts / "releasekit.sh")
write_file(
scripts / "check-examples.py",
"""
import os
from pathlib import Path
marker = Path(os.environ["FIXTURE_EXAMPLE_MARKER"])
with marker.open("a", encoding="utf-8") as stream:
stream.write("called\\n")
""",
)
write_file(
repository / f"docs/releases/{RELEASE_VERSION}.md",
f"""
# Promptkit {RELEASE_VERSION}
Disposable publication fixture.
""",
)
fixture_sources(repository, environment)
repo_git(repository, environment, "add", "-A")
run(
["git", "-C", str(repository), "commit", "-m", "Add disposable release fixture"],
cwd=repository.parent,
environment=environment,
)
repo_git(repository, environment, "push", "origin", "main")
def verify_publication(repository, remote, temporary_root, environment, module_bytes, selected_go):
bootstrap = repository / "scripts/releasekit.sh"
run(
[str(bootstrap), "publish", RELEASE_VERSION],
cwd=temporary_root,
environment=environment,
)
suite_lines = Path(environment["FIXTURE_SUITE_MARKER"]).read_text(
encoding="utf-8"
).splitlines()
if len(suite_lines) != 1:
raise RuntimeError(f"expected one suite marker, found {len(suite_lines)}")
suite_record = json.loads(suite_lines[0])
if suite_record != {"go_version": selected_go, "race": True}:
raise RuntimeError(f"unexpected suite marker: {suite_record!r}")
example_lines = Path(environment["FIXTURE_EXAMPLE_MARKER"]).read_text(
encoding="utf-8"
).splitlines()
if example_lines != ["called"]:
raise RuntimeError(f"expected one additional-check marker, got {example_lines!r}")
binary = repository / ".releasekit/bin/releasekit"
if not binary.is_file():
raise RuntimeError("ReleaseKit bootstrap did not leave its ignored executable")
build_info = run(
["go", "version", "-m", str(binary)],
cwd=temporary_root,
environment=environment,
)
first_line = build_info.splitlines()[0]
if selected_go not in first_line:
raise RuntimeError(f"tool was built with {first_line!r}, expected {selected_go}")
expected_module = f"\tmod\t{RELEASEKIT_MODULE}\tv0.2.0\t"
if expected_module not in build_info:
raise RuntimeError("bootstrap executable does not record ReleaseKit v0.2.0")
candidate = repo_git(repository, environment, "rev-parse", "HEAD").strip()
if repo_git(repository, environment, "rev-parse", "main").strip() != candidate:
raise RuntimeError("fixture main moved away from the published candidate")
if remote_git(remote, temporary_root, environment, "rev-parse", "refs/heads/main").strip() != candidate:
raise RuntimeError("local origin main does not identify the fixture candidate")
tag_ref = f"refs/tags/{RELEASE_VERSION}"
if repo_git(repository, environment, "cat-file", "-t", tag_ref).strip() != "tag":
raise RuntimeError("local release ref is not an annotated tag")
local_tag = repo_git(repository, environment, "rev-parse", tag_ref).strip()
local_tag_commit = repo_git(
repository, environment, "rev-parse", f"{tag_ref}^{{}}"
).strip()
if local_tag_commit != candidate:
raise RuntimeError("local annotated tag does not identify the fixture candidate")
remote_tag = remote_git(remote, temporary_root, environment, "rev-parse", tag_ref).strip()
remote_tag_commit = remote_git(
remote, temporary_root, environment, "rev-parse", f"{tag_ref}^{{}}"
).strip()
if remote_tag != local_tag or remote_tag_commit != candidate:
raise RuntimeError("remote annotated tag does not identify the fixture candidate")
if remote_git(
remote, temporary_root, environment, "cat-file", "-t", tag_ref
).strip() != "tag":
raise RuntimeError("remote release ref is not an annotated tag")
tag_object = repo_git(repository, environment, "cat-file", "tag", tag_ref)
separator = tag_object.find("\n\n")
if separator < 0:
raise RuntimeError("annotated tag has no message")
tag_message = tag_object[separator + 2 :]
note = (repository / f"docs/releases/{RELEASE_VERSION}.md").read_text(
encoding="utf-8"
)
if tag_message != note:
raise RuntimeError("annotated tag message does not match the committed release note")
for name, contents in module_bytes.items():
if (repository / name).read_bytes() != contents:
raise RuntimeError(f"publication changed {name}")
status = repo_git(
repository, environment, "status", "--porcelain", "--untracked-files=all"
)
if status:
raise RuntimeError(f"fixture checkout is not clean after publication:\n{status}")
repo_git(repository, environment, "check-ignore", "-q", ".releasekit/bin/releasekit")
def main():
environment = os.environ.copy()
environment.update(
{
"GOTOOLCHAIN": "local",
"GOWORK": "off",
"GOPROXY": "off",
"GONOPROXY": "none",
"GOSUMDB": "off",
}
)
selected_go = run(
["go", "env", "GOVERSION"],
cwd=REPOSITORY_ROOT,
environment=environment,
).strip()
if not selected_go:
print("go env GOVERSION returned no version", file=sys.stderr)
return 1
ignored_rule = ".releasekit/"
ignore_lines = (REPOSITORY_ROOT / ".gitignore").read_text(
encoding="utf-8"
).splitlines()
if ignored_rule not in ignore_lines:
print(".gitignore does not contain the ReleaseKit output rule", file=sys.stderr)
return 1
module_bytes = {
name: (REPOSITORY_ROOT / name).read_bytes() for name in ("go.mod", "go.sum")
}
with tempfile.TemporaryDirectory(prefix="promptkit-release-fixture-") as directory:
temporary_root = Path(directory)
repository = temporary_root / "checkout"
remote = temporary_root / "origin.git"
suite_marker = temporary_root / "suite.jsonl"
example_marker = temporary_root / "example.log"
environment["FIXTURE_SUITE_MARKER"] = str(suite_marker)
environment["FIXTURE_EXAMPLE_MARKER"] = str(example_marker)
try:
prepare_repository(repository, remote, environment, module_bytes)
verify_publication(
repository,
remote,
temporary_root,
environment,
module_bytes,
selected_go,
)
except (RuntimeError, OSError, json.JSONDecodeError) as error:
print(error, file=sys.stderr)
return 1
print("ReleaseKit successful-publication fixture passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())