sase-github 0.2.8__tar.gz → 0.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. sase_github-0.2.9/.release-please-manifest.json +3 -0
  2. {sase_github-0.2.8 → sase_github-0.2.9}/CHANGELOG.md +7 -0
  3. {sase_github-0.2.8 → sase_github-0.2.9}/PKG-INFO +1 -1
  4. {sase_github-0.2.8 → sase_github-0.2.9}/pyproject.toml +1 -1
  5. sase_github-0.2.9/src/sase_github/scripts/gh_release.py +27 -0
  6. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/xprompts/gh.yml +7 -10
  7. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_gh_workspace_claims.py +90 -7
  8. sase_github-0.2.8/.release-please-manifest.json +0 -3
  9. {sase_github-0.2.8 → sase_github-0.2.9}/.github/workflows/ci.yml +0 -0
  10. {sase_github-0.2.8 → sase_github-0.2.9}/.github/workflows/pr-title.yml +0 -0
  11. {sase_github-0.2.8 → sase_github-0.2.9}/.github/workflows/publish.yml +0 -0
  12. {sase_github-0.2.8 → sase_github-0.2.9}/.sase_beads/beads.db +0 -0
  13. {sase_github-0.2.8 → sase_github-0.2.9}/.sase_beads/config.json +0 -0
  14. {sase_github-0.2.8 → sase_github-0.2.9}/.sase_beads/issues.jsonl +0 -0
  15. {sase_github-0.2.8 → sase_github-0.2.9}/CLAUDE.md +0 -0
  16. {sase_github-0.2.8 → sase_github-0.2.9}/Justfile +0 -0
  17. {sase_github-0.2.8 → sase_github-0.2.9}/LICENSE +0 -0
  18. {sase_github-0.2.8 → sase_github-0.2.9}/README.md +0 -0
  19. {sase_github-0.2.8 → sase_github-0.2.9}/docs/architecture.md +0 -0
  20. {sase_github-0.2.8 → sase_github-0.2.9}/docs/configuration.md +0 -0
  21. {sase_github-0.2.8 → sase_github-0.2.9}/docs/xprompts.md +0 -0
  22. {sase_github-0.2.8 → sase_github-0.2.9}/release-please-config.json +0 -0
  23. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/__init__.py +0 -0
  24. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/config.py +0 -0
  25. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/default_config.yml +0 -0
  26. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/errors.py +0 -0
  27. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/plugin.py +0 -0
  28. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/scripts/__init__.py +0 -0
  29. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/scripts/gh_setup.py +0 -0
  30. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/scripts/new_pr_desc_get_context.py +0 -0
  31. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/task_types.py +0 -0
  32. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/workspace_plugin.py +0 -0
  33. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/xprompts/new_pr_desc.yml +0 -0
  34. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/xprompts/pr_diff.yml +0 -0
  35. {sase_github-0.2.8 → sase_github-0.2.9}/src/sase_github/xprompts/prdd.yml +0 -0
  36. {sase_github-0.2.8 → sase_github-0.2.9}/tests/__init__.py +0 -0
  37. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_ci_install_contract.py +0 -0
  38. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_config.py +0 -0
  39. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_github_issues.py +0 -0
  40. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_github_plugin.py +0 -0
  41. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_github_pull_requests.py +0 -0
  42. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_submit_with_recorded_pr.py +0 -0
  43. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_task_types.py +0 -0
  44. {sase_github-0.2.8 → sase_github-0.2.9}/tests/test_workspace_plugin.py +0 -0
  45. {sase_github-0.2.8 → sase_github-0.2.9}/uv.lock +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.9"
3
+ }
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.9](https://github.com/sase-org/sase-github/compare/v0.2.8...v0.2.9) (2026-08-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * **workspace:** identity-check #gh release and skip on handoff ([2571c9d](https://github.com/sase-org/sase-github/commit/2571c9d7466d4c6020a87b6ee86068c12170cdab))
9
+
3
10
  ## [0.2.8](https://github.com/sase-org/sase-github/compare/v0.2.7...v0.2.8) (2026-08-29)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sase-github
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: GitHub VCS plugin for sase
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sase-github"
7
- version = "0.2.8"
7
+ version = "0.2.9"
8
8
  description = "GitHub VCS plugin for sase"
9
9
  requires-python = ">=3.12"
10
10
  license = "MIT"
@@ -0,0 +1,27 @@
1
+ """Release step for the #gh xprompt workflow."""
2
+
3
+ from sase.workspace_provider.vcs_release import VcsReleaseResult, release_vcs_workspace
4
+
5
+ _CALLER_TAG = "gh-release"
6
+
7
+
8
+ def main(
9
+ *,
10
+ project_file: str,
11
+ workspace_num: int,
12
+ workspace_dir: str,
13
+ workflow_name: str,
14
+ cl_name: str | None,
15
+ ) -> None:
16
+ """Identity-checked, handoff-aware release of the #gh workspace claim."""
17
+ result: VcsReleaseResult = release_vcs_workspace(
18
+ project_file=project_file,
19
+ workspace_num=workspace_num,
20
+ workspace_dir=workspace_dir,
21
+ workflow_name=workflow_name,
22
+ cl_name=cl_name,
23
+ caller_tag=_CALLER_TAG,
24
+ )
25
+ print(f"released={'true' if result.released else 'false'}")
26
+ if result.skip_reason:
27
+ print(f"skip_reason={result.skip_reason}")
@@ -120,18 +120,15 @@ steps:
120
120
  finally: true
121
121
  if: "{{ setup.should_release }}"
122
122
  python: |
123
- from sase.running_field import release_workspace
124
- from sase.workspace_provider.occupant import clear_occupant_record
123
+ from sase_github.scripts.gh_release import main
125
124
 
126
- release_workspace(
127
- {{ setup.project_file | tojson }},
128
- {{ setup.workspace_num }},
129
- {{ setup.workflow_name | tojson }},
130
- {{ gh_ref | tojson }} if "/" not in {{ gh_ref | tojson }} else None,
131
- caller_tag="gh-release",
125
+ main(
126
+ project_file={{ setup.project_file | tojson }},
127
+ workspace_num={{ setup.workspace_num }},
128
+ workspace_dir={{ setup.workspace_dir | tojson }},
129
+ workflow_name={{ setup.workflow_name | tojson }},
130
+ cl_name={{ gh_ref | tojson }} if "/" not in {{ gh_ref | tojson }} else None,
132
131
  )
133
- clear_occupant_record({{ setup.workspace_dir | tojson }})
134
- print("released=true")
135
132
  output: { released: bool }
136
133
 
137
134
  - name: diff
@@ -23,7 +23,7 @@ from sase.workspace_provider.occupant import (
23
23
  write_occupant_record,
24
24
  )
25
25
 
26
- from sase_github.scripts import gh_setup
26
+ from sase_github.scripts import gh_release, gh_setup
27
27
  from sase_github.workspace_plugin import GitHubWorkspacePlugin
28
28
 
29
29
  ROOT = Path(__file__).resolve().parents[1]
@@ -939,16 +939,99 @@ class TestWsSubmitAtomicClaim:
939
939
  )
940
940
 
941
941
 
942
- def test_gh_release_step_tags_caller() -> None:
942
+ def test_gh_release_step_delegates_to_gh_release() -> None:
943
943
  text = (ROOT / "src" / "sase_github" / "xprompts" / "gh.yml").read_text(
944
944
  encoding="utf-8"
945
945
  )
946
- assert 'caller_tag="gh-release"' in text
946
+ assert "from sase_github.scripts.gh_release import main" in text
947
+ assert "workspace_dir={{ setup.workspace_dir | tojson }}" in text
948
+ assert "release_workspace(" not in text
949
+ assert "clear_occupant_record(" not in text
947
950
 
948
951
 
949
- def test_gh_release_step_clears_occupant_record() -> None:
950
- text = (ROOT / "src" / "sase_github" / "xprompts" / "gh.yml").read_text(
952
+ def test_gh_release_caller_tag() -> None:
953
+ source = (ROOT / "src" / "sase_github" / "scripts" / "gh_release.py").read_text(
951
954
  encoding="utf-8"
952
955
  )
953
- assert "clear_occupant_record(" in text
954
- assert "setup.workspace_dir" in text.split("clear_occupant_record(", 1)[1]
956
+ assert '_CALLER_TAG = "gh-release"' in source
957
+
958
+
959
+ def test_gh_release_step_releases_owned_claim_and_occupant(
960
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
961
+ ) -> None:
962
+ runner_pid = os.getppid()
963
+ project_file = _write_project_file(
964
+ tmp_path,
965
+ running_claims=[WorkspaceClaim(23, "gh-acme/widget", None, pid=runner_pid)],
966
+ )
967
+ workspace_dir = tmp_path / "widget_23"
968
+ workspace_dir.mkdir()
969
+ write_occupant_record(
970
+ str(workspace_dir),
971
+ new_occupant_record(
972
+ pid=runner_pid,
973
+ workflow="gh-acme/widget",
974
+ project="gh_acme__widget",
975
+ workspace_num=23,
976
+ ),
977
+ )
978
+
979
+ with _isolate_ledger(tmp_path):
980
+ gh_release.main(
981
+ project_file=project_file,
982
+ workspace_num=23,
983
+ workspace_dir=str(workspace_dir),
984
+ workflow_name="gh-acme/widget",
985
+ cl_name=None,
986
+ )
987
+
988
+ out = capsys.readouterr().out
989
+ assert "released=true" in out
990
+ assert get_claimed_workspaces(project_file) == []
991
+ assert read_occupant_record(str(workspace_dir)) is None
992
+
993
+
994
+ def test_gh_release_step_skips_on_handoff(
995
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
996
+ ) -> None:
997
+ runner_pid = os.getppid()
998
+ project_file = _write_project_file(
999
+ tmp_path,
1000
+ running_claims=[WorkspaceClaim(23, "gh-acme/widget", None, pid=runner_pid)],
1001
+ )
1002
+ workspace_dir = tmp_path / "widget_23"
1003
+ workspace_dir.mkdir()
1004
+ write_occupant_record(
1005
+ str(workspace_dir),
1006
+ new_occupant_record(
1007
+ pid=runner_pid,
1008
+ workflow="gh-acme/widget",
1009
+ project="gh_acme__widget",
1010
+ workspace_num=23,
1011
+ ),
1012
+ )
1013
+ artifacts = tmp_path / "artifacts"
1014
+ artifacts.mkdir()
1015
+ (artifacts / ".sase_monitor_pending").write_text("{}", encoding="utf-8")
1016
+
1017
+ with (
1018
+ _isolate_ledger(tmp_path),
1019
+ patch.dict(os.environ, {"SASE_ARTIFACTS_DIR": str(artifacts)}),
1020
+ ):
1021
+ gh_release.main(
1022
+ project_file=project_file,
1023
+ workspace_num=23,
1024
+ workspace_dir=str(workspace_dir),
1025
+ workflow_name="gh-acme/widget",
1026
+ cl_name=None,
1027
+ )
1028
+
1029
+ out = capsys.readouterr().out
1030
+ assert "released=false" in out
1031
+ assert "skip_reason=handoff" in out
1032
+ assert [claim.workspace_num for claim in get_claimed_workspaces(project_file)] == [
1033
+ 23
1034
+ ]
1035
+ occupant = read_occupant_record(str(workspace_dir))
1036
+ assert occupant is not None
1037
+ assert occupant.pid == runner_pid
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.2.8"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes