main
py 123 lines 4.71 KB
Raw
1 import importlib.util
2 import subprocess
3 import sys
4 from pathlib import Path
5
6
7 PROJECT_ROOT = Path(__file__).resolve().parents[1]
8 MODULE_PATH = PROJECT_ROOT / ".github" / "scripts" / "docker_release_plan.py"
9
10
11 def load_module():
12 spec = importlib.util.spec_from_file_location("docker_release_plan", MODULE_PATH)
13 module = importlib.util.module_from_spec(spec)
14 assert spec.loader is not None
15 sys.modules[spec.name] = module
16 spec.loader.exec_module(module)
17 return module
18
19
20 def git(repo: Path, *args: str) -> str:
21 result = subprocess.run(
22 ["git", *args],
23 cwd=repo,
24 check=True,
25 capture_output=True,
26 text=True,
27 )
28 return result.stdout.strip()
29
30
31 def commit_file(repo: Path, name: str, content: str, message: str) -> str:
32 (repo / name).write_text(content, encoding="utf-8")
33 git(repo, "add", name)
34 git(repo, "commit", "-m", message)
35 return git(repo, "rev-parse", "HEAD")
36
37
38 def seed_remote_refs(repo: Path, *branches: str) -> None:
39 for branch in branches:
40 git(repo, "update-ref", f"refs/remotes/origin/{branch}", git(repo, "rev-parse", branch))
41
42
43 def test_docker_publish_workflow_tracks_branch_promotions():
44 workflow_path = PROJECT_ROOT / ".github" / "workflows" / "docker-publish.yml"
45 content = workflow_path.read_text(encoding="utf-8")
46
47 assert 'branches:\n - "testing"\n - "main"' in content
48 assert 'tags:\n - "v*"' in content
49 assert "workflow_dispatch:" in content
50 assert "inputs:" in content
51 assert "tag:" in content
52 assert 'ref: ${{ matrix.source_tag }}' in content
53 assert "SOURCE_REF_TYPE: ${{ github.ref_type }}" in content
54 assert "BEFORE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }}" in content
55
56
57 def test_plan_branch_push_builds_when_tag_reaches_allowed_branch(monkeypatch, tmp_path: Path):
58 release_plan = load_module()
59
60 git(tmp_path, "init", "-b", "main")
61 git(tmp_path, "config", "user.name", "Test User")
62 git(tmp_path, "config", "user.email", "test@example.com")
63
64 commit_file(tmp_path, "README.md", "base\n", "base")
65 git(tmp_path, "tag", "v1.6")
66 git(tmp_path, "branch", "testing")
67
68 git(tmp_path, "checkout", "-b", "development")
69 git(tmp_path, "checkout", "main")
70 git(tmp_path, "merge", "--ff-only", "development")
71
72 git(tmp_path, "checkout", "development")
73 commit_file(tmp_path, "feature.txt", "release\n", "release v1.7")
74 git(tmp_path, "tag", "v1.7")
75
76 testing_before = git(tmp_path, "rev-parse", "testing")
77 git(tmp_path, "checkout", "testing")
78 git(tmp_path, "merge", "--no-ff", "development", "-m", "promote v1.7 to testing")
79
80 git(tmp_path, "checkout", "main")
81 git(tmp_path, "merge", "--no-ff", "development", "-m", "promote v1.7 to main")
82 seed_remote_refs(tmp_path, "testing", "main")
83
84 monkeypatch.chdir(tmp_path)
85 monkeypatch.setenv("ALLOWED_BRANCHES", "testing main")
86 monkeypatch.setenv("MAIN_BRANCH", "main")
87 monkeypatch.setenv("DOCKER_IMAGE_REPO", "example/agent-zero")
88 monkeypatch.setenv("RELEASE_TAG_REGEX", r"^v([0-9]+)\.([0-9]+)$")
89 monkeypatch.setenv("MIN_RELEASE_MAJOR", "1")
90 monkeypatch.setenv("MIN_RELEASE_MINOR", "0")
91 monkeypatch.setenv("EVENT_NAME", "push")
92 monkeypatch.setenv("SOURCE_REF_TYPE", "branch")
93 monkeypatch.setenv("MANUAL_TAG", "")
94 monkeypatch.setenv("AFTER_SHA", git(tmp_path, "rev-parse", "testing"))
95
96 monkeypatch.setenv("SOURCE_REF_NAME", "testing")
97 monkeypatch.setenv("BEFORE_SHA", testing_before)
98 config = release_plan.load_config()
99 branch_states = release_plan.collect_branch_states(config)
100 testing_candidates, testing_notes = release_plan.plan_branch_push(config, branch_states)
101
102 assert testing_notes == []
103 assert len(testing_candidates) == 1
104 assert testing_candidates[0].branch == "testing"
105 assert testing_candidates[0].source_tag == "v1.7"
106 assert testing_candidates[0].mode == "push_promoted_tag"
107 assert testing_candidates[0].publish_version is False
108 assert testing_candidates[0].publish_branch_tag is True
109
110 monkeypatch.setenv("SOURCE_REF_NAME", "main")
111 monkeypatch.setenv("BEFORE_SHA", git(tmp_path, "rev-list", "--max-parents=0", "HEAD"))
112 monkeypatch.setenv("AFTER_SHA", git(tmp_path, "rev-parse", "main"))
113 config = release_plan.load_config()
114 branch_states = release_plan.collect_branch_states(config)
115 main_candidates, main_notes = release_plan.plan_branch_push(config, branch_states)
116
117 assert main_notes == []
118 assert len(main_candidates) == 1
119 assert main_candidates[0].branch == "main"
120 assert main_candidates[0].source_tag == "v1.7"
121 assert main_candidates[0].mode == "push_promoted_tag"
122 assert main_candidates[0].publish_version is True
123 assert main_candidates[0].publish_branch_tag is True