sscbirrt 3.0.0__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 (144) hide show
  1. sscbirrt-3.0.0/.github/CODEOWNERS +1 -0
  2. sscbirrt-3.0.0/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
  3. sscbirrt-3.0.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. sscbirrt-3.0.0/.github/ISSUE_TEMPLATE/improvement.md +13 -0
  5. sscbirrt-3.0.0/.github/ISSUE_TEMPLATE/task.md +12 -0
  6. sscbirrt-3.0.0/.github/pull_request_template.md +24 -0
  7. sscbirrt-3.0.0/.github/workflows/ci.yml +172 -0
  8. sscbirrt-3.0.0/.github/workflows/release.yml +152 -0
  9. sscbirrt-3.0.0/.gitignore +37 -0
  10. sscbirrt-3.0.0/CHANGELOG.md +560 -0
  11. sscbirrt-3.0.0/CODE_OF_CONDUCT.md +13 -0
  12. sscbirrt-3.0.0/CONTRIBUTING.md +50 -0
  13. sscbirrt-3.0.0/LICENSE +21 -0
  14. sscbirrt-3.0.0/PKG-INFO +655 -0
  15. sscbirrt-3.0.0/README.md +608 -0
  16. sscbirrt-3.0.0/SECURITY.md +7 -0
  17. sscbirrt-3.0.0/cpp/CMakeLists.txt +270 -0
  18. sscbirrt-3.0.0/cpp/README.md +46 -0
  19. sscbirrt-3.0.0/cpp/bindings/sscbirrt_native.cpp +347 -0
  20. sscbirrt-3.0.0/cpp/bindings/sscbirrt_native_mujoco.cpp +134 -0
  21. sscbirrt-3.0.0/cpp/cmake/sscbirrtConfig.cmake.in +4 -0
  22. sscbirrt-3.0.0/cpp/examples/consumer/CMakeLists.txt +9 -0
  23. sscbirrt-3.0.0/cpp/examples/consumer/main.cpp +45 -0
  24. sscbirrt-3.0.0/cpp/examples/consumer/smoke.sh +12 -0
  25. sscbirrt-3.0.0/cpp/include/sscbirrt/cancel.hpp +29 -0
  26. sscbirrt-3.0.0/cpp/include/sscbirrt/config.hpp +43 -0
  27. sscbirrt-3.0.0/cpp/include/sscbirrt/detail/sha256.hpp +31 -0
  28. sscbirrt-3.0.0/cpp/include/sscbirrt/errors.hpp +50 -0
  29. sscbirrt-3.0.0/cpp/include/sscbirrt/kinematics.hpp +29 -0
  30. sscbirrt-3.0.0/cpp/include/sscbirrt/motion.hpp +55 -0
  31. sscbirrt-3.0.0/cpp/include/sscbirrt/mujoco/scene.hpp +71 -0
  32. sscbirrt-3.0.0/cpp/include/sscbirrt/mujoco/snapshot.hpp +35 -0
  33. sscbirrt-3.0.0/cpp/include/sscbirrt/mujoco/validator.hpp +48 -0
  34. sscbirrt-3.0.0/cpp/include/sscbirrt/planner.hpp +37 -0
  35. sscbirrt-3.0.0/cpp/include/sscbirrt/problem.hpp +26 -0
  36. sscbirrt-3.0.0/cpp/include/sscbirrt/result.hpp +72 -0
  37. sscbirrt-3.0.0/cpp/include/sscbirrt/sets.hpp +238 -0
  38. sscbirrt-3.0.0/cpp/include/sscbirrt/space.hpp +51 -0
  39. sscbirrt-3.0.0/cpp/include/sscbirrt/sscbirrt.hpp +19 -0
  40. sscbirrt-3.0.0/cpp/include/sscbirrt/ssik/ssik_arm.hpp +61 -0
  41. sscbirrt-3.0.0/cpp/include/sscbirrt/transform.hpp +45 -0
  42. sscbirrt-3.0.0/cpp/include/sscbirrt/tsr/tsr.hpp +57 -0
  43. sscbirrt-3.0.0/cpp/include/sscbirrt/tsr/tsr_set.hpp +62 -0
  44. sscbirrt-3.0.0/cpp/include/sscbirrt/types.hpp +41 -0
  45. sscbirrt-3.0.0/cpp/include/sscbirrt/validity.hpp +39 -0
  46. sscbirrt-3.0.0/cpp/src/config.cpp +39 -0
  47. sscbirrt-3.0.0/cpp/src/motion.cpp +73 -0
  48. sscbirrt-3.0.0/cpp/src/mujoco/scene.cpp +145 -0
  49. sscbirrt-3.0.0/cpp/src/mujoco/sha256.cpp +91 -0
  50. sscbirrt-3.0.0/cpp/src/mujoco/snapshot.cpp +85 -0
  51. sscbirrt-3.0.0/cpp/src/mujoco/validator.cpp +102 -0
  52. sscbirrt-3.0.0/cpp/src/planner.cpp +517 -0
  53. sscbirrt-3.0.0/cpp/src/sets.cpp +429 -0
  54. sscbirrt-3.0.0/cpp/src/space.cpp +118 -0
  55. sscbirrt-3.0.0/cpp/src/ssik/ssik_arm.cpp +109 -0
  56. sscbirrt-3.0.0/cpp/src/transform.cpp +131 -0
  57. sscbirrt-3.0.0/cpp/src/tsr/tsr.cpp +205 -0
  58. sscbirrt-3.0.0/cpp/src/tsr/tsr_set.cpp +93 -0
  59. sscbirrt-3.0.0/cpp/tests/harness.hpp +81 -0
  60. sscbirrt-3.0.0/cpp/tests/test_motion.cpp +58 -0
  61. sscbirrt-3.0.0/cpp/tests/test_mujoco_scene.cpp +201 -0
  62. sscbirrt-3.0.0/cpp/tests/test_mujoco_validator.cpp +143 -0
  63. sscbirrt-3.0.0/cpp/tests/test_planner.cpp +356 -0
  64. sscbirrt-3.0.0/cpp/tests/test_sets.cpp +185 -0
  65. sscbirrt-3.0.0/cpp/tests/test_space.cpp +80 -0
  66. sscbirrt-3.0.0/cpp/tests/test_tsr.cpp +92 -0
  67. sscbirrt-3.0.0/cpp/tests/test_tsr_set.cpp +194 -0
  68. sscbirrt-3.0.0/docs/design.md +360 -0
  69. sscbirrt-3.0.0/docs/images/example1_result.png +0 -0
  70. sscbirrt-3.0.0/docs/images/example2_result.png +0 -0
  71. sscbirrt-3.0.0/docs/images/example3_result.png +0 -0
  72. sscbirrt-3.0.0/docs/images/tsr_union_demo.gif +0 -0
  73. sscbirrt-3.0.0/docs/migration-mj-manipulator.md +77 -0
  74. sscbirrt-3.0.0/docs/native-design.md +1549 -0
  75. sscbirrt-3.0.0/examples/multi_config_demo.py +104 -0
  76. sscbirrt-3.0.0/examples/planar_arm.py +685 -0
  77. sscbirrt-3.0.0/examples/tsr_union_demo.py +559 -0
  78. sscbirrt-3.0.0/examples/ur5e_mujoco.py +429 -0
  79. sscbirrt-3.0.0/examples/ur5e_transport.py +135 -0
  80. sscbirrt-3.0.0/pyproject.toml +115 -0
  81. sscbirrt-3.0.0/src/sscbirrt/__init__.py +78 -0
  82. sscbirrt-3.0.0/src/sscbirrt/backends/__init__.py +4 -0
  83. sscbirrt-3.0.0/src/sscbirrt/backends/mujoco.py +498 -0
  84. sscbirrt-3.0.0/src/sscbirrt/backends/native.py +418 -0
  85. sscbirrt-3.0.0/src/sscbirrt/backends/native_mujoco.py +283 -0
  86. sscbirrt-3.0.0/src/sscbirrt/backends/native_ssik.py +47 -0
  87. sscbirrt-3.0.0/src/sscbirrt/backends/ssik.py +179 -0
  88. sscbirrt-3.0.0/src/sscbirrt/config.py +104 -0
  89. sscbirrt-3.0.0/src/sscbirrt/exceptions.py +80 -0
  90. sscbirrt-3.0.0/src/sscbirrt/interfaces/__init__.py +8 -0
  91. sscbirrt-3.0.0/src/sscbirrt/interfaces/collision_checker.py +21 -0
  92. sscbirrt-3.0.0/src/sscbirrt/interfaces/ik_solver.py +35 -0
  93. sscbirrt-3.0.0/src/sscbirrt/interfaces/robot_model.py +31 -0
  94. sscbirrt-3.0.0/src/sscbirrt/legacy.py +105 -0
  95. sscbirrt-3.0.0/src/sscbirrt/motion.py +131 -0
  96. sscbirrt-3.0.0/src/sscbirrt/planner.py +844 -0
  97. sscbirrt-3.0.0/src/sscbirrt/problem.py +60 -0
  98. sscbirrt-3.0.0/src/sscbirrt/sets.py +628 -0
  99. sscbirrt-3.0.0/src/sscbirrt/space.py +172 -0
  100. sscbirrt-3.0.0/src/sscbirrt/testing/__init__.py +8 -0
  101. sscbirrt-3.0.0/src/sscbirrt/testing/planar.py +78 -0
  102. sscbirrt-3.0.0/src/sscbirrt/tree.py +111 -0
  103. sscbirrt-3.0.0/src/sscbirrt/tsr_set.py +182 -0
  104. sscbirrt-3.0.0/tests/__init__.py +0 -0
  105. sscbirrt-3.0.0/tests/reference/benchmark_native.json +167 -0
  106. sscbirrt-3.0.0/tests/reference/mujoco_collision_corpus.json +7197 -0
  107. sscbirrt-3.0.0/tests/reference/python_reference.json +3604 -0
  108. sscbirrt-3.0.0/tests/reference/tsr_conformance.json +10307 -0
  109. sscbirrt-3.0.0/tests/test_admissibility.py +294 -0
  110. sscbirrt-3.0.0/tests/test_cancellation.py +88 -0
  111. sscbirrt-3.0.0/tests/test_composition_planning.py +134 -0
  112. sscbirrt-3.0.0/tests/test_config_validation.py +65 -0
  113. sscbirrt-3.0.0/tests/test_connection.py +238 -0
  114. sscbirrt-3.0.0/tests/test_examples.py +29 -0
  115. sscbirrt-3.0.0/tests/test_examples_mujoco.py +118 -0
  116. sscbirrt-3.0.0/tests/test_motion.py +456 -0
  117. sscbirrt-3.0.0/tests/test_mujoco_collision_corpus.py +148 -0
  118. sscbirrt-3.0.0/tests/test_mujoco_ik.py +197 -0
  119. sscbirrt-3.0.0/tests/test_native_backend.py +459 -0
  120. sscbirrt-3.0.0/tests/test_native_isolation.py +137 -0
  121. sscbirrt-3.0.0/tests/test_native_mujoco_plan.py +146 -0
  122. sscbirrt-3.0.0/tests/test_native_mujoco_scene.py +164 -0
  123. sscbirrt-3.0.0/tests/test_native_ssik.py +115 -0
  124. sscbirrt-3.0.0/tests/test_planner.py +1115 -0
  125. sscbirrt-3.0.0/tests/test_problem.py +177 -0
  126. sscbirrt-3.0.0/tests/test_query_space.py +112 -0
  127. sscbirrt-3.0.0/tests/test_reference_artifact.py +135 -0
  128. sscbirrt-3.0.0/tests/test_sampler.py +92 -0
  129. sscbirrt-3.0.0/tests/test_seeds.py +340 -0
  130. sscbirrt-3.0.0/tests/test_sets.py +377 -0
  131. sscbirrt-3.0.0/tests/test_sets_properties.py +290 -0
  132. sscbirrt-3.0.0/tests/test_space.py +134 -0
  133. sscbirrt-3.0.0/tests/test_ssik_backend.py +280 -0
  134. sscbirrt-3.0.0/tests/test_tolerances.py +198 -0
  135. sscbirrt-3.0.0/tests/test_tsr_chain_set.py +228 -0
  136. sscbirrt-3.0.0/tests/test_tsr_conformance.py +108 -0
  137. sscbirrt-3.0.0/tests/test_tsr_set.py +194 -0
  138. sscbirrt-3.0.0/tests/test_unwrap.py +137 -0
  139. sscbirrt-3.0.0/tests/test_ur5e_integration.py +191 -0
  140. sscbirrt-3.0.0/tests/test_violation.py +276 -0
  141. sscbirrt-3.0.0/tools/benchmark_native.py +129 -0
  142. sscbirrt-3.0.0/tools/mujoco_collision_corpus.py +261 -0
  143. sscbirrt-3.0.0/tools/reference_artifact.py +820 -0
  144. sscbirrt-3.0.0/tools/tsr_conformance.py +197 -0
@@ -0,0 +1 @@
1
+ * @siddhss5
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a reproducible bug
4
+ labels: bug
5
+ ---
6
+
7
+ ## Environment
8
+ - OS:
9
+ - Python version:
10
+ - uv version:
11
+ - Package version or commit:
12
+
13
+ ## Reproduction
14
+ <!-- Minimal steps to reproduce the problem. -->
15
+
16
+ ## Expected behavior
17
+
18
+ ## Actual behavior
19
+
20
+ ## Logs / traceback
21
+ ```
22
+ ```
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Questions and discussion
4
+ url: https://github.com/personalrobotics/robot-code/discussions
5
+ about: Ask questions or discuss design in the umbrella repo.
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: Improvement
3
+ about: Propose an enhancement to existing functionality
4
+ labels: enhancement
5
+ ---
6
+
7
+ ## Motivation
8
+ <!-- What problem or limitation prompts this improvement? -->
9
+
10
+ ## Proposal
11
+ <!-- What should change, concretely? -->
12
+
13
+ ## Alternatives considered
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: Task
3
+ about: A planned unit of work
4
+ labels: task
5
+ ---
6
+
7
+ ## Goal
8
+
9
+ ## Acceptance criteria
10
+ - [ ]
11
+
12
+ ## Notes
@@ -0,0 +1,24 @@
1
+ ## Summary
2
+
3
+ <!-- One or two sentences describing what this PR does and why. -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Bulleted list of the concrete changes made. -->
8
+ -
9
+
10
+ ## Testing
11
+
12
+ - [ ] `uv run pytest tests/ -v` passes
13
+ - [ ] `uv run ruff check .` passes
14
+ - [ ] `uv run ruff format --check .` passes
15
+ - [ ] Integration tested locally against the robot-code workspace (if cross-repo)
16
+
17
+ ## Breaking changes
18
+
19
+ - [ ] None
20
+ - [ ] Yes (describe migration below):
21
+
22
+ ## Related issues
23
+
24
+ <!-- e.g. Fixes #123, Part of personalrobotics/robot-code#3 -->
@@ -0,0 +1,172 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ concurrency:
11
+ group: ci-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ test:
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: ["3.10", "3.11", "3.12"]
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Set up uv
25
+ uses: astral-sh/setup-uv@v5
26
+ with:
27
+ enable-cache: true
28
+ python-version: ${{ matrix.python-version }}
29
+
30
+ - name: Install system dependencies
31
+ run: sudo apt-get update && sudo apt-get install -y libeigen3-dev
32
+
33
+ - name: Install dependencies (builds the extension; ssik is a build requirement, so the SSIK adapter is detected)
34
+ run: |
35
+ uv sync --all-extras --dev
36
+ uv run python -c "import sscbirrt._native as n; assert n.has_ssik(), n.ssik_unavailable_reason(); print('native SSIK adapter built')"
37
+ uv run python -c "from sscbirrt.backends import native_mujoco as m; assert m.available(), m.unavailable_reason(); print('native MuJoCo scene built')"
38
+
39
+ - name: Ruff lint
40
+ run: uv run ruff check .
41
+
42
+ - name: Ruff format check
43
+ run: uv run ruff format --check .
44
+
45
+ - name: Pytest
46
+ run: |
47
+ if [ -d tests ]; then
48
+ uv run pytest tests/ -v
49
+ else
50
+ echo "No tests/ directory; skipping pytest."
51
+ fi
52
+
53
+ cpp:
54
+ name: C++ core (sanitizers)
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+ - uses: astral-sh/setup-uv@v5
59
+ with:
60
+ python-version: "3.12"
61
+ - name: Install Eigen and the ssik headers (for the SSIK adapter under sanitizers)
62
+ run: |
63
+ sudo apt-get update && sudo apt-get install -y libeigen3-dev
64
+ uv venv "$RUNNER_TEMP/ssik-env"
65
+ uv pip install --python "$RUNNER_TEMP/ssik-env/bin/python" "ssik>=7.0,<8"
66
+ echo "SSIK_CMAKE_DIR=$("$RUNNER_TEMP/ssik-env/bin/python" -c 'import ssik; print(ssik.get_cmake_dir())')" >> "$GITHUB_ENV"
67
+ uv pip install --python "$RUNNER_TEMP/ssik-env/bin/python" "mujoco==3.14.0"
68
+ echo "MUJOCO_DIR=$("$RUNNER_TEMP/ssik-env/bin/python" -c 'import mujoco, os; print(os.path.dirname(mujoco.__file__))')" >> "$GITHUB_ENV"
69
+ - name: Configure
70
+ run: cmake -S cpp -B build/cpp -DCMAKE_BUILD_TYPE=Debug -DSSCBIRRT_SANITIZE=ON -DSSCBIRRT_WITH_SSIK=ON -DSSCBIRRT_SSIK_CMAKE_DIR="$SSIK_CMAKE_DIR" -DSSCBIRRT_WITH_MUJOCO=ON -DSSCBIRRT_MUJOCO_DIR="$MUJOCO_DIR"
71
+ - name: Build
72
+ run: cmake --build build/cpp --parallel
73
+ - name: Test
74
+ run: ctest --test-dir build/cpp --output-on-failure
75
+
76
+ cpp-consumer:
77
+ name: C++ consumer (installed package)
78
+ runs-on: ubuntu-latest
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+ - name: Install, then build and run the standalone consumer against the installed package
82
+ run: cpp/examples/consumer/smoke.sh "$RUNNER_TEMP/sscbirrt"
83
+
84
+ package:
85
+ name: Wheel and sdist in clean environments
86
+ runs-on: ubuntu-latest
87
+ steps:
88
+ - uses: actions/checkout@v4
89
+ - uses: astral-sh/setup-uv@v5
90
+ with:
91
+ python-version: "3.12"
92
+ - name: Install Eigen (ssik, a build requirement, supplies the ssik_cpp headers to the isolated build)
93
+ run: sudo apt-get update && sudo apt-get install -y libeigen3-dev
94
+ - name: Build the wheel and the sdist
95
+ run: uv build
96
+ - name: Install the wheel into a fresh environment and plan natively
97
+ run: |
98
+ uv venv --python 3.12 "$RUNNER_TEMP/wheel-env"
99
+ uv pip install --python "$RUNNER_TEMP/wheel-env/bin/python" dist/*.whl
100
+ "$RUNNER_TEMP/wheel-env/bin/python" -c "
101
+ import sscbirrt._native as n; assert n.has_ssik(), n.ssik_unavailable_reason()
102
+ import numpy as np
103
+ from sscbirrt import CBiRRT, CBiRRTConfig, FiniteSet, PlanningProblem
104
+ from sscbirrt.testing import NoCollision, PlanarArm, PlanarIK
105
+ p = CBiRRT(PlanarArm(), PlanarIK(), NoCollision(), CBiRRTConfig(step_size=0.2), backend='native')
106
+ f = lambda qs: FiniteSet(qs, tolerance=1e-3, metric=p.space.distance)
107
+ r = p.solve(PlanningProblem(space=p.space, start=f([np.zeros(2)]), goal=f([np.array([1.0, 0.5])]), validator=p.collision), seed=0)
108
+ assert r.success and r.backend == 'native', r
109
+ print('wheel ok:', len(r.path), 'waypoints natively')
110
+ "
111
+ - name: Without mujoco installed, sscbirrt imports and the MuJoCo scene reports its reason
112
+ run: |
113
+ "$RUNNER_TEMP/wheel-env/bin/python" -c "
114
+ import sscbirrt
115
+ from sscbirrt.backends import native_mujoco as m
116
+ assert not m.available() and 'mujoco is not installed' in m.unavailable_reason(), m.unavailable_reason()
117
+ print('no-mujoco import ok:', m.unavailable_reason())
118
+ "
119
+ - name: With the mujoco extra, the native scene loads against the pinned MuJoCo
120
+ run: |
121
+ uv pip install --python "$RUNNER_TEMP/wheel-env/bin/python" "$(ls dist/*.whl)[mujoco]"
122
+ "$RUNNER_TEMP/wheel-env/bin/python" -c "
123
+ import mujoco
124
+ from sscbirrt.backends import native_mujoco as m
125
+ assert m.available(), m.unavailable_reason()
126
+ model = mujoco.MjModel.from_xml_string('<mujoco><worldbody><body><joint name=\"j\" type=\"hinge\"/><geom size=\"0.1\"/></body></worldbody></mujoco>')
127
+ s = m.NativeScene.from_model(model, ['j']); print('scene ok:', s.provenance)
128
+ "
129
+ - name: Install the sdist into a fresh environment (compiles from source)
130
+ run: |
131
+ uv venv --python 3.12 "$RUNNER_TEMP/sdist-env"
132
+ uv pip install --python "$RUNNER_TEMP/sdist-env/bin/python" dist/*.tar.gz
133
+ "$RUNNER_TEMP/sdist-env/bin/python" -c "import sscbirrt._native as n; print('sdist ok; ssik adapter:', n.has_ssik())"
134
+
135
+ package-macos:
136
+ name: Wheel on macOS (arm64)
137
+ runs-on: macos-latest
138
+ steps:
139
+ - uses: actions/checkout@v4
140
+ - uses: astral-sh/setup-uv@v5
141
+ with:
142
+ python-version: "3.12"
143
+ - name: Install Eigen
144
+ run: brew install eigen
145
+ - name: Build the wheel (ssik and mujoco are build requirements; both native adapters must be present)
146
+ run: uv build --wheel
147
+ - name: Install into a fresh environment with every extra and exercise every native module
148
+ run: |
149
+ uv venv --python 3.12 "$RUNNER_TEMP/mac-env"
150
+ uv pip install --python "$RUNNER_TEMP/mac-env/bin/python" "$(ls dist/*.whl)[ssik,mujoco]"
151
+ "$RUNNER_TEMP/mac-env/bin/python" -c "
152
+ import mujoco, numpy as np
153
+ import sscbirrt._native as n; assert n.has_ssik(), n.ssik_unavailable_reason()
154
+ from sscbirrt.backends import native_mujoco as m; assert m.available(), m.unavailable_reason()
155
+ model = mujoco.MjModel.from_xml_string('<mujoco><worldbody><body><joint name=\"j\" type=\"hinge\"/><geom size=\"0.1\"/></body></worldbody></mujoco>')
156
+ s = m.NativeScene.from_model(model, ['j']); print('macOS wheel: ssik and mujoco native modules ok', s.provenance['mujoco'])
157
+ "
158
+ "$RUNNER_TEMP/mac-env/bin/python" tools/reference_artifact.py --backend native --check
159
+ "$RUNNER_TEMP/mac-env/bin/python" tools/reference_artifact.py --backend auto --check
160
+
161
+ notify-robot-code:
162
+ needs: [test, cpp, cpp-consumer, package, package-macos]
163
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
164
+ runs-on: ubuntu-latest
165
+ steps:
166
+ - name: Dispatch integration run
167
+ uses: peter-evans/repository-dispatch@v3
168
+ with:
169
+ token: ${{ secrets.ROBOT_CODE_DISPATCH_TOKEN }}
170
+ repository: personalrobotics/robot-code
171
+ event-type: sibling-updated
172
+ client-payload: '{"repo":"${{ github.event.repository.name }}","sha":"${{ github.sha }}"}'
@@ -0,0 +1,152 @@
1
+ name: Release
2
+
3
+ # Tag-driven release pipeline (#153), on the ssik pattern.
4
+ #
5
+ # v*rc* build wheels + sdist, publish to TestPyPI (the dry run; the artifacts may carry the
6
+ # final version the tag rehearses, e.g. v3.0.0rc1 on the commit whose version is 3.0.0)
7
+ # v* build wheels + sdist, publish to PyPI, create the GitHub release from the CHANGELOG
8
+ # workflow_dispatch build wheels + sdist only; publishes to TestPyPI only with publish_testpypi=true
9
+ #
10
+ # Auth: Trusted Publishing (PyPI / TestPyPI OIDC). No API tokens. The publish jobs run inside the GitHub
11
+ # environments `release` and `testpypi-release` so environment-protection rules apply.
12
+ #
13
+ # The wheel matrix and the repair rules live in pyproject.toml under [tool.cibuildwheel]: CPython 3.10 to
14
+ # 3.14 on manylinux_2_28 x86_64 and macOS arm64, libmujoco excluded from bundling, every wheel installed
15
+ # with [mujoco,ssik] and run through the reference artifact check before it is kept.
16
+
17
+ on:
18
+ push:
19
+ tags: ["v*"]
20
+ workflow_dispatch:
21
+ inputs:
22
+ publish_testpypi:
23
+ description: "Also publish the built artifacts to TestPyPI"
24
+ type: boolean
25
+ default: false
26
+
27
+ permissions:
28
+ contents: read
29
+
30
+ jobs:
31
+ build_wheels:
32
+ name: Wheels on ${{ matrix.os }}
33
+ runs-on: ${{ matrix.os }}
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ os: [ubuntu-latest, macos-latest]
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ - name: Build and test wheels
41
+ uses: pypa/cibuildwheel@v3.4.1
42
+ - uses: actions/upload-artifact@v4
43
+ with:
44
+ name: wheels-${{ matrix.os }}
45
+ path: wheelhouse/*.whl
46
+
47
+ build_sdist:
48
+ name: Source distribution
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: astral-sh/setup-uv@v5
53
+ with:
54
+ python-version: "3.12"
55
+ - name: Build the sdist
56
+ run: uv build --sdist
57
+ - name: The sdist compiles on a machine with no Eigen (the build downloads the pinned one)
58
+ run: |
59
+ uv venv --python 3.12 "$RUNNER_TEMP/sdist-env"
60
+ uv pip install --python "$RUNNER_TEMP/sdist-env/bin/python" dist/*.tar.gz
61
+ "$RUNNER_TEMP/sdist-env/bin/python" -c "import sscbirrt._native as n; assert n.has_ssik(), n.ssik_unavailable_reason(); print('sdist ok; SSIK adapter built against the downloaded Eigen')"
62
+ - uses: actions/upload-artifact@v4
63
+ with:
64
+ name: sdist
65
+ path: dist/*.tar.gz
66
+
67
+ publish_testpypi:
68
+ name: Publish to TestPyPI
69
+ needs: [build_wheels, build_sdist]
70
+ runs-on: ubuntu-latest
71
+ if: >-
72
+ (startsWith(github.ref, 'refs/tags/v') && contains(github.ref, 'rc')) ||
73
+ (github.event_name == 'workflow_dispatch' && inputs.publish_testpypi)
74
+ environment:
75
+ name: testpypi-release
76
+ url: https://test.pypi.org/p/sscbirrt
77
+ permissions:
78
+ id-token: write
79
+ steps:
80
+ - uses: actions/download-artifact@v4
81
+ with:
82
+ path: dist
83
+ merge-multiple: true
84
+ - name: Every artifact carries the tag's version (an rc tag may carry the final version it rehearses)
85
+ if: startsWith(github.ref, 'refs/tags/v')
86
+ run: |
87
+ TAG="${GITHUB_REF#refs/tags/v}"; BASE="${TAG%%rc*}"; ls -1 dist/
88
+ for f in dist/*; do
89
+ case "$(basename "$f")" in
90
+ sscbirrt-"$TAG".tar.gz|sscbirrt-"$TAG"-*.whl|sscbirrt-"$BASE".tar.gz|sscbirrt-"$BASE"-*.whl) ;;
91
+ *) echo "::error::$(basename "$f") is neither version $TAG nor $BASE (pyproject version and tag must agree)"; exit 1 ;;
92
+ esac
93
+ done
94
+ echo "OK: all artifacts are version $TAG or $BASE"
95
+ - uses: pypa/gh-action-pypi-publish@release/v1
96
+ with:
97
+ repository-url: https://test.pypi.org/legacy/
98
+
99
+ publish_pypi:
100
+ name: Publish to PyPI
101
+ needs: [build_wheels, build_sdist]
102
+ runs-on: ubuntu-latest
103
+ if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'rc')
104
+ environment:
105
+ name: release
106
+ url: https://pypi.org/p/sscbirrt
107
+ permissions:
108
+ id-token: write
109
+ steps:
110
+ - uses: actions/download-artifact@v4
111
+ with:
112
+ path: dist
113
+ merge-multiple: true
114
+ - name: Every artifact carries the tag's version
115
+ run: |
116
+ TAG="${GITHUB_REF#refs/tags/v}"; ls -1 dist/
117
+ for f in dist/*; do
118
+ case "$(basename "$f")" in
119
+ sscbirrt-"$TAG".tar.gz|sscbirrt-"$TAG"-*.whl) ;;
120
+ *) echo "::error::$(basename "$f") is not version $TAG (pyproject version and tag must agree)"; exit 1 ;;
121
+ esac
122
+ done
123
+ echo "OK: all artifacts are version $TAG"
124
+ - uses: pypa/gh-action-pypi-publish@release/v1
125
+
126
+ github_release:
127
+ name: GitHub release from the CHANGELOG
128
+ needs: publish_pypi
129
+ runs-on: ubuntu-latest
130
+ if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'rc')
131
+ permissions:
132
+ contents: write
133
+ steps:
134
+ - uses: actions/checkout@v4
135
+ - name: Extract this version's CHANGELOG section
136
+ run: |
137
+ TAG="${GITHUB_REF#refs/tags/v}"
138
+ python3 - "$TAG" <<'PY' > notes.md
139
+ import re, sys, pathlib
140
+ tag = sys.argv[1]
141
+ text = pathlib.Path("CHANGELOG.md").read_text()
142
+ m = re.search(rf"^## \[{re.escape(tag)}\][^\n]*\n(.*?)(?=^## \[|\Z)", text, re.S | re.M)
143
+ if not m:
144
+ sys.exit(f"CHANGELOG.md has no section for {tag}")
145
+ print(m.group(1).strip())
146
+ PY
147
+ test -s notes.md
148
+ - uses: softprops/action-gh-release@v2
149
+ with:
150
+ tag_name: ${{ github.ref_name }}
151
+ name: ${{ github.ref_name }}
152
+ body_path: notes.md
@@ -0,0 +1,37 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ venv/
14
+ .venv/
15
+ env/
16
+
17
+ # IDE
18
+ .idea/
19
+ .vscode/
20
+ *.swp
21
+ *.swo
22
+
23
+ # Testing
24
+ .pytest_cache/
25
+ .coverage
26
+ htmlcov/
27
+
28
+ # OS
29
+ .DS_Store
30
+ Thumbs.db
31
+
32
+ # Generated files
33
+ *.png
34
+ !docs/images/*.png
35
+
36
+ # MuJoCo writes this next to the process when it warns
37
+ MUJOCO_LOG.TXT