ray-hive 1.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 (99) hide show
  1. ray_hive-1.0/.gitattributes +3 -0
  2. ray_hive-1.0/.github/CODEOWNERS +1 -0
  3. ray_hive-1.0/.github/ISSUE_TEMPLATE/bug.yml +39 -0
  4. ray_hive-1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. ray_hive-1.0/.github/ISSUE_TEMPLATE/feature.yml +33 -0
  6. ray_hive-1.0/.github/PULL_REQUEST_TEMPLATE.md +31 -0
  7. ray_hive-1.0/.github/workflows/ci.yml +147 -0
  8. ray_hive-1.0/.github/workflows/hive-integration.yml +46 -0
  9. ray_hive-1.0/.github/workflows/release.yml +345 -0
  10. ray_hive-1.0/.github/workflows/slow-integration.yml +30 -0
  11. ray_hive-1.0/.gitignore +14 -0
  12. ray_hive-1.0/.pre-commit-config.yaml +38 -0
  13. ray_hive-1.0/CHANGELOG.md +15 -0
  14. ray_hive-1.0/CONTRIBUTING.md +61 -0
  15. ray_hive-1.0/LICENSE +201 -0
  16. ray_hive-1.0/NOTICE +5 -0
  17. ray_hive-1.0/PKG-INFO +163 -0
  18. ray_hive-1.0/README.md +122 -0
  19. ray_hive-1.0/SECURITY.md +36 -0
  20. ray_hive-1.0/docs/adr/strict-single-query.md +14 -0
  21. ray_hive-1.0/docs/architecture.md +44 -0
  22. ray_hive-1.0/docs/compatibility.md +42 -0
  23. ray_hive-1.0/docs/conformance.md +19 -0
  24. ray_hive-1.0/docs/consistency.md +25 -0
  25. ray_hive-1.0/docs/errors.md +28 -0
  26. ray_hive-1.0/docs/index.md +13 -0
  27. ray_hive-1.0/docs/security.md +34 -0
  28. ray_hive-1.0/mkdocs.yml +25 -0
  29. ray_hive-1.0/pyproject.toml +102 -0
  30. ray_hive-1.0/release-notes/v1.0.md +32 -0
  31. ray_hive-1.0/scripts/__init__.py +13 -0
  32. ray_hive-1.0/scripts/check_license_headers.py +40 -0
  33. ray_hive-1.0/scripts/check_release.py +67 -0
  34. ray_hive-1.0/scripts/check_spec.py +137 -0
  35. ray_hive-1.0/scripts/generate_thrift_stubs.py +122 -0
  36. ray_hive-1.0/scripts/run_hive_it.sh +44 -0
  37. ray_hive-1.0/scripts/setup_hive_it.py +117 -0
  38. ray_hive-1.0/scripts/thrift-compiler.Dockerfile +8 -0
  39. ray_hive-1.0/scripts/validate_release_candidate.py +140 -0
  40. ray_hive-1.0/scripts/verify_release_artifacts.py +117 -0
  41. ray_hive-1.0/scripts/verify_release_tag.py +56 -0
  42. ray_hive-1.0/spec/hs2-arrow/v1/SPEC_VERSION +1 -0
  43. ray_hive-1.0/spec/hs2-arrow/v1/capabilities.json +15 -0
  44. ray_hive-1.0/spec/hs2-arrow/v1/errors.json +17 -0
  45. ray_hive-1.0/spec/hs2-arrow/v1/expected/primitive-v6.json +12 -0
  46. ray_hive-1.0/spec/hs2-arrow/v1/fixtures/primitive-v6.json +8 -0
  47. ray_hive-1.0/spec/hs2-arrow/v1/manifest.json +36 -0
  48. ray_hive-1.0/spec/hs2-arrow/v1/schema/errors.schema.json +24 -0
  49. ray_hive-1.0/spec/hs2-arrow/v1/schema/manifest.schema.json +48 -0
  50. ray_hive-1.0/src/ray_hive/__init__.py +64 -0
  51. ray_hive-1.0/src/ray_hive/_api.py +40 -0
  52. ray_hive-1.0/src/ray_hive/_capabilities.py +70 -0
  53. ray_hive-1.0/src/ray_hive/_compat.py +120 -0
  54. ray_hive-1.0/src/ray_hive/_credentials.py +140 -0
  55. ray_hive-1.0/src/ray_hive/_errors.py +157 -0
  56. ray_hive-1.0/src/ray_hive/_hs2/__init__.py +15 -0
  57. ray_hive-1.0/src/ray_hive/_hs2/client.py +447 -0
  58. ray_hive-1.0/src/ray_hive/_hs2/decoder.py +119 -0
  59. ray_hive-1.0/src/ray_hive/_hs2/generated/README.md +19 -0
  60. ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/TCLIService-remote +285 -0
  61. ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/TCLIService.py +5334 -0
  62. ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/__init__.py +1 -0
  63. ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/constants.py +72 -0
  64. ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/ttypes.py +9014 -0
  65. ray_hive-1.0/src/ray_hive/_hs2/generated/__init__.py +15 -0
  66. ray_hive-1.0/src/ray_hive/_hs2/generated/idl/TCLIService.thrift +1350 -0
  67. ray_hive-1.0/src/ray_hive/_hs2/operation.py +120 -0
  68. ray_hive-1.0/src/ray_hive/_hs2/protocol.py +227 -0
  69. ray_hive-1.0/src/ray_hive/_hs2/session.py +108 -0
  70. ray_hive-1.0/src/ray_hive/_hs2/transport.py +275 -0
  71. ray_hive-1.0/src/ray_hive/_models.py +356 -0
  72. ray_hive-1.0/src/ray_hive/_planner.py +172 -0
  73. ray_hive-1.0/src/ray_hive/_schema.py +121 -0
  74. ray_hive-1.0/src/ray_hive/_sql.py +218 -0
  75. ray_hive-1.0/src/ray_hive/_task_spec.py +48 -0
  76. ray_hive-1.0/src/ray_hive/_telemetry.py +25 -0
  77. ray_hive-1.0/src/ray_hive/_worker.py +323 -0
  78. ray_hive-1.0/src/ray_hive/datasource.py +90 -0
  79. ray_hive-1.0/src/ray_hive/py.typed +1 -0
  80. ray_hive-1.0/src/ray_hive/sql.py +19 -0
  81. ray_hive-1.0/tests/__init__.py +13 -0
  82. ray_hive-1.0/tests/_fakes.py +128 -0
  83. ray_hive-1.0/tests/contract/test_native_protocol_contract.py +250 -0
  84. ray_hive-1.0/tests/contract/test_spec.py +25 -0
  85. ray_hive-1.0/tests/integration/docker-compose.yml +28 -0
  86. ray_hive-1.0/tests/integration/setup.sql +42 -0
  87. ray_hive-1.0/tests/integration/test_hive_420.py +168 -0
  88. ray_hive-1.0/tests/unit/test_capabilities_errors.py +88 -0
  89. ray_hive-1.0/tests/unit/test_client_transport_edges.py +651 -0
  90. ray_hive-1.0/tests/unit/test_compat_datasource.py +171 -0
  91. ray_hive-1.0/tests/unit/test_models_credentials.py +215 -0
  92. ray_hive-1.0/tests/unit/test_operation_planner.py +266 -0
  93. ray_hive-1.0/tests/unit/test_release.py +74 -0
  94. ray_hive-1.0/tests/unit/test_schema_decoder.py +186 -0
  95. ray_hive-1.0/tests/unit/test_session_worker_edges.py +384 -0
  96. ray_hive-1.0/tests/unit/test_setup_hive_it.py +90 -0
  97. ray_hive-1.0/tests/unit/test_sql.py +91 -0
  98. ray_hive-1.0/tests/unit/test_worker.py +297 -0
  99. ray_hive-1.0/uv.lock +1321 -0
@@ -0,0 +1,3 @@
1
+ * text=auto eol=lf
2
+ *.bat text eol=crlf
3
+ src/ray_hive/_hs2/generated/idl/TCLIService.thrift -whitespace
@@ -0,0 +1 @@
1
+ * @jiangxt2
@@ -0,0 +1,39 @@
1
+ name: Bug report
2
+ description: Report a reproducible ray-hive defect without sensitive data
3
+ title: "[Bug] "
4
+ labels: [bug]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: Do not include credentials, full connection URLs, private SQL, or row values.
9
+ - type: input
10
+ id: version
11
+ attributes:
12
+ label: ray-hive version or commit
13
+ validations:
14
+ required: true
15
+ - type: textarea
16
+ id: environment
17
+ attributes:
18
+ label: Environment
19
+ description: Include Python, Ray, PyArrow, Hive, driver, transport, and authentication mode.
20
+ validations:
21
+ required: true
22
+ - type: textarea
23
+ id: reproduction
24
+ attributes:
25
+ label: Minimal reproduction
26
+ description: Use sanitized identifiers and values.
27
+ validations:
28
+ required: true
29
+ - type: textarea
30
+ id: behavior
31
+ attributes:
32
+ label: Expected and actual behavior
33
+ validations:
34
+ required: true
35
+ - type: textarea
36
+ id: diagnostics
37
+ attributes:
38
+ label: Sanitized diagnostics
39
+ description: Include stable error code and operation state, but no full SQL or secrets.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://github.com/jiangxt2/ray-hive/security/advisories/new
5
+ about: Report vulnerabilities privately; do not open a public issue.
@@ -0,0 +1,33 @@
1
+ name: Feature request
2
+ description: Propose a scoped datasource capability
3
+ title: "[Feature] "
4
+ labels: [enhancement]
5
+ body:
6
+ - type: textarea
7
+ id: problem
8
+ attributes:
9
+ label: Problem
10
+ description: Describe the user need independently of a proposed implementation.
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: scope
15
+ attributes:
16
+ label: Proposed scope
17
+ description: Identify API, driver, transport, auth, type, consistency, and version boundaries.
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: evidence
22
+ attributes:
23
+ label: Required conformance evidence
24
+ description: List real Hive, security, failure, or Ray cluster cases needed for the claim.
25
+ validations:
26
+ required: true
27
+ - type: checkboxes
28
+ id: purity
29
+ attributes:
30
+ label: Data-plane boundary
31
+ options:
32
+ - label: The proposal keeps all table and storage access behind HiveServer2.
33
+ required: true
@@ -0,0 +1,31 @@
1
+ ## What changes
2
+
3
+ Describe the public behavior and the implementation boundaries changed by this pull request.
4
+
5
+ ## Why
6
+
7
+ Explain the correctness, compatibility, security, or maintainability need.
8
+
9
+ ## User-facing impact
10
+
11
+ Describe API, compatibility, performance, consistency, or migration impact. Write `None` only when
12
+ the change is genuinely internal.
13
+
14
+ ## How tested
15
+
16
+ - [ ] Ruff format and lint
17
+ - [ ] mypy
18
+ - [ ] Unit and contract tests with coverage
19
+ - [ ] License, codespell, documentation, and conformance checks
20
+ - [ ] Real Hive 4.2.0 integration tests when required
21
+ - [ ] Ray cluster or slow infrastructure tests when required
22
+ - [ ] Package build, isolated install, and import smoke
23
+
24
+ List exact commands and infrastructure versions below.
25
+
26
+ ## Checklist
27
+
28
+ - [ ] I used only public Ray APIs outside `ray_hive._compat`.
29
+ - [ ] I added no storage, filesystem, HMS, or table-location fallback.
30
+ - [ ] I documented any consistency or capability change without broadening unverified claims.
31
+ - [ ] Every commit has a valid `Signed-off-by` trailer.
@@ -0,0 +1,147 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [master]
7
+ workflow_call:
8
+ inputs:
9
+ candidate_sha:
10
+ required: false
11
+ type: string
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ dco:
22
+ name: DCO
23
+ runs-on: ubuntu-latest
24
+ timeout-minutes: 5
25
+ steps:
26
+ - name: Check out full history
27
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28
+ with:
29
+ fetch-depth: 0
30
+ ref: ${{ inputs.candidate_sha || github.sha }}
31
+ - name: Install Python for reusable release validation
32
+ if: github.event_name == 'workflow_call'
33
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
34
+ with:
35
+ python-version: "3.12"
36
+ - name: Validate every commit trailer
37
+ env:
38
+ BEFORE_SHA: ${{ github.event.before }}
39
+ HEAD_SHA: ${{ github.sha }}
40
+ PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
41
+ run: |
42
+ set -euo pipefail
43
+ zero=0000000000000000000000000000000000000000
44
+ if [[ -n "${PR_BASE_SHA}" ]]; then
45
+ range="${PR_BASE_SHA}..${HEAD_SHA}"
46
+ elif [[ -n "${BEFORE_SHA}" && "${BEFORE_SHA}" != "${zero}" ]]; then
47
+ range="${BEFORE_SHA}..${HEAD_SHA}"
48
+ else
49
+ range="${HEAD_SHA}"
50
+ fi
51
+ failed=0
52
+ while read -r commit; do
53
+ if ! git show -s --format=%B "${commit}" | grep -Eiq '^Signed-off-by: .+ <[^>]+>$'; then
54
+ echo "Missing valid Signed-off-by trailer: ${commit}"
55
+ failed=1
56
+ fi
57
+ done < <(git rev-list "${range}")
58
+ exit "${failed}"
59
+ - name: Validate DCO for the release candidate
60
+ if: github.event_name == 'workflow_call'
61
+ run: python scripts/check_dco.py "${{ inputs.candidate_sha }}"
62
+
63
+ static:
64
+ name: Static and docs
65
+ runs-on: ubuntu-latest
66
+ timeout-minutes: 15
67
+ steps:
68
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
69
+ with:
70
+ ref: ${{ inputs.candidate_sha || github.sha }}
71
+ - name: Install uv and Python
72
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
73
+ with:
74
+ version: "0.12.0"
75
+ python-version: "3.12"
76
+ enable-cache: true
77
+ - run: uv sync --frozen --extra dev --extra telemetry
78
+ - run: uv run --frozen ruff format --check .
79
+ - run: uv run --frozen ruff check .
80
+ - run: uv run --frozen mypy
81
+ - run: uv run --frozen python scripts/check_license_headers.py
82
+ - run: uv run --frozen python scripts/check_spec.py
83
+ - run: uv run --frozen codespell
84
+ - run: uv run --frozen mkdocs build --strict
85
+
86
+ unit-contract:
87
+ name: Unit and contract (Python ${{ matrix.python-version }})
88
+ runs-on: ubuntu-latest
89
+ timeout-minutes: 20
90
+ strategy:
91
+ fail-fast: false
92
+ matrix:
93
+ python-version: ["3.12", "3.13"]
94
+ steps:
95
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
96
+ with:
97
+ ref: ${{ inputs.candidate_sha || github.sha }}
98
+ - name: Install uv and Python
99
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
100
+ with:
101
+ version: "0.12.0"
102
+ python-version: ${{ matrix.python-version }}
103
+ enable-cache: true
104
+ cache-suffix: py${{ matrix.python-version }}
105
+ - run: uv sync --frozen --extra dev --extra telemetry
106
+ - name: Run collected unit and contract gates
107
+ run: >-
108
+ uv run --frozen python -m pytest tests/unit tests/contract
109
+ --cov=ray_hive --cov-report=term-missing --cov-report=xml
110
+
111
+ thrift-codegen:
112
+ name: Reproducible Thrift bindings
113
+ runs-on: ubuntu-latest
114
+ timeout-minutes: 15
115
+ steps:
116
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
117
+ with:
118
+ ref: ${{ inputs.candidate_sha || github.sha }}
119
+ - name: Install uv and Python
120
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
121
+ with:
122
+ version: "0.12.0"
123
+ python-version: "3.12"
124
+ - run: uv sync --frozen --extra dev
125
+ - run: uv run --frozen python scripts/generate_thrift_stubs.py --build-image --check
126
+
127
+ package:
128
+ name: Package
129
+ runs-on: ubuntu-latest
130
+ timeout-minutes: 15
131
+ steps:
132
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
133
+ with:
134
+ ref: ${{ inputs.candidate_sha || github.sha }}
135
+ - name: Install uv and Python
136
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
137
+ with:
138
+ version: "0.12.0"
139
+ python-version: "3.12"
140
+ - run: uv sync --frozen --extra dev --extra telemetry
141
+ - run: uv run --frozen python -m build
142
+ - run: uv run --frozen twine check dist/*
143
+ - name: Isolated wheel import smoke
144
+ run: |
145
+ uv venv /tmp/ray-hive-wheel-smoke --python 3.12
146
+ uv pip install --python /tmp/ray-hive-wheel-smoke/bin/python dist/*.whl
147
+ /tmp/ray-hive-wheel-smoke/bin/python -c 'import ray_hive; print(ray_hive.__all__)'
@@ -0,0 +1,46 @@
1
+ name: Hive integration
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [master]
7
+ workflow_dispatch:
8
+ workflow_call:
9
+ inputs:
10
+ candidate_sha:
11
+ required: false
12
+ type: string
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: hive-it-${{ github.event.pull_request.number || github.ref }}
19
+ cancel-in-progress: true
20
+
21
+ jobs:
22
+ hive-420:
23
+ name: Apache Hive 4.2.0
24
+ runs-on: ubuntu-latest
25
+ timeout-minutes: 40
26
+ steps:
27
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28
+ with:
29
+ ref: ${{ inputs.candidate_sha || github.sha }}
30
+ - name: Install uv and Python
31
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
32
+ with:
33
+ version: "0.12.0"
34
+ python-version: "3.12"
35
+ enable-cache: true
36
+ - run: uv sync --frozen --extra dev --extra telemetry
37
+ - name: Run exact ray-hive-it infrastructure
38
+ run: ./scripts/run_hive_it.sh
39
+ - name: Preserve Hive logs
40
+ if: always()
41
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
42
+ with:
43
+ name: hive-420-${{ github.run_id }}-${{ github.run_attempt }}
44
+ path: tests/integration/logs/
45
+ if-no-files-found: error
46
+ retention-days: 14
@@ -0,0 +1,345 @@
1
+ # Copyright 2026 ray-hive contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ name: Release
16
+
17
+ on:
18
+ push:
19
+ tags: ["v*"]
20
+ workflow_dispatch:
21
+ inputs:
22
+ candidate_sha:
23
+ description: "Commit SHA to validate; required for a manual run"
24
+ required: true
25
+ type: string
26
+ expected_version:
27
+ description: "Expected project version, for example 1.0"
28
+ required: true
29
+ type: string
30
+ formal_publish:
31
+ description: "Publish to TestPyPI, PyPI, and GitHub Releases"
32
+ required: true
33
+ default: false
34
+ type: boolean
35
+ release_tag:
36
+ description: "Existing annotated tag to publish, for example v1.0"
37
+ required: true
38
+ default: "v1.0"
39
+ type: string
40
+
41
+ permissions:
42
+ contents: read
43
+
44
+ concurrency:
45
+ group: release-${{ github.ref }}
46
+ cancel-in-progress: false
47
+
48
+ jobs:
49
+ candidate:
50
+ name: Validate release candidate
51
+ runs-on: ubuntu-latest
52
+ timeout-minutes: 10
53
+ outputs:
54
+ mode: ${{ steps.validate.outputs.mode }}
55
+ sha: ${{ steps.validate.outputs.sha }}
56
+ version: ${{ steps.validate.outputs.version }}
57
+ tag: ${{ steps.validate.outputs.tag }}
58
+ master_sha: ${{ steps.validate.outputs.master_sha }}
59
+ steps:
60
+ - name: Check out protected master and tags
61
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
62
+ with:
63
+ ref: master
64
+ fetch-depth: 0
65
+ persist-credentials: false
66
+ - name: Set up Python
67
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
68
+ with:
69
+ python-version: "3.12"
70
+ - name: Validate candidate ancestry, identity, and tag event
71
+ id: validate
72
+ env:
73
+ MODE: ${{ (github.event_name == 'push' || inputs.formal_publish == true) && 'tag' || 'dry-run' }}
74
+ CANDIDATE_REF: ${{ github.event_name == 'push' && github.sha || inputs.candidate_sha }}
75
+ EXPECTED_VERSION: ${{ github.event_name == 'push' && '' || inputs.expected_version }}
76
+ RELEASE_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.release_tag }}
77
+ EVENT_SHA: ${{ github.event_name == 'push' && github.sha || inputs.candidate_sha }}
78
+ EVENT_CREATED: ${{ github.event_name == 'push' && github.event.created || inputs.formal_publish }}
79
+ EVENT_DELETED: ${{ github.event_name == 'push' && github.event.deleted || 'false' }}
80
+ EVENT_FORCED: ${{ github.event_name == 'push' && github.event.forced || 'false' }}
81
+ run: >-
82
+ python scripts/validate_release_candidate.py
83
+ --mode "${MODE}"
84
+ --candidate-ref "${CANDIDATE_REF}"
85
+ --expected-version "${EXPECTED_VERSION}"
86
+ --tag "${RELEASE_TAG}"
87
+ --event-sha "${EVENT_SHA}"
88
+ --event-created "${EVENT_CREATED}"
89
+ --event-deleted "${EVENT_DELETED}"
90
+ --event-forced "${EVENT_FORCED}"
91
+ --github-output "${GITHUB_OUTPUT}"
92
+
93
+ gates:
94
+ name: Run complete CI gates on candidate
95
+ needs: candidate
96
+ uses: ./.github/workflows/ci.yml
97
+ with:
98
+ candidate_sha: ${{ needs.candidate.outputs.sha }}
99
+
100
+ hive:
101
+ name: Run real Hive gate on candidate
102
+ needs: candidate
103
+ uses: ./.github/workflows/hive-integration.yml
104
+ with:
105
+ candidate_sha: ${{ needs.candidate.outputs.sha }}
106
+
107
+ build:
108
+ name: Build and attest one immutable artifact
109
+ needs: [candidate, gates, hive]
110
+ if: needs.candidate.result == 'success' && needs.gates.result == 'success' && needs.hive.result == 'success'
111
+ runs-on: ubuntu-latest
112
+ timeout-minutes: 30
113
+ outputs:
114
+ artifact-id: ${{ steps.upload.outputs.artifact-id }}
115
+ permissions:
116
+ contents: read
117
+ id-token: write
118
+ attestations: write
119
+ steps:
120
+ - name: Check out candidate
121
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
122
+ with:
123
+ ref: ${{ needs.candidate.outputs.sha }}
124
+ fetch-depth: 0
125
+ persist-credentials: false
126
+ - name: Install uv and Python
127
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
128
+ with:
129
+ version: "0.12.0"
130
+ python-version: "3.12"
131
+ enable-cache: true
132
+ - run: uv sync --frozen --extra dev --extra telemetry
133
+ - name: Verify release identity and credential scan
134
+ run: uv run --frozen python scripts/check_release.py --tag "${{ needs.candidate.outputs.tag }}"
135
+ - run: uv run --frozen python scripts/check_spec.py
136
+ - name: Build distributions
137
+ run: uv run --frozen python -m build --outdir release-artifacts/packages
138
+ - name: Check distribution metadata
139
+ run: uv run --frozen twine check release-artifacts/packages/*
140
+ - name: Generate SHA-256 manifest
141
+ run: >-
142
+ uv run --frozen python scripts/verify_release_artifacts.py
143
+ release-artifacts/packages
144
+ --name ray-hive
145
+ --version "${{ needs.candidate.outputs.version }}"
146
+ --manifest release-artifacts/SHA256SUMS
147
+ --prepare
148
+ - name: Generate SPDX JSON SBOM
149
+ uses: anchore/sbom-action@a930d0ac434e3182448fe678398ba5713717112a # v0.21.0
150
+ with:
151
+ path: .
152
+ format: spdx-json
153
+ output-file: release-artifacts/ray-hive.spdx.json
154
+ upload-artifact: false
155
+ - name: Attest release artifacts
156
+ uses: actions/attest-build-provenance@8beda2b7ed98355c0e97c0a63bec38ae472e66c4 # v4
157
+ with:
158
+ subject-path: release-artifacts/packages/*
159
+ - name: Upload immutable release bundle
160
+ id: upload
161
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
162
+ with:
163
+ name: release-bundle
164
+ path: release-artifacts/
165
+ if-no-files-found: error
166
+ retention-days: 14
167
+
168
+ install-smoke:
169
+ name: Install ${{ matrix.artifact }} / ${{ matrix.profile }} / Python ${{ matrix.python }}
170
+ needs: [candidate, build]
171
+ if: needs.build.result == 'success'
172
+ runs-on: ubuntu-latest
173
+ timeout-minutes: 20
174
+ strategy:
175
+ fail-fast: false
176
+ matrix:
177
+ python: ["3.12", "3.13"]
178
+ artifact: [wheel, sdist]
179
+ profile: [base, telemetry]
180
+ steps:
181
+ - name: Download exact release bundle
182
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
183
+ with:
184
+ artifact-ids: ${{ needs.build.outputs.artifact-id }}
185
+ path: release
186
+ merge-multiple: true
187
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
188
+ with:
189
+ python-version: ${{ matrix.python }}
190
+ - name: Install exact distribution
191
+ env:
192
+ PROFILE: ${{ matrix.profile }}
193
+ ARTIFACT: ${{ matrix.artifact }}
194
+ run: |
195
+ set -euo pipefail
196
+ if [[ "${ARTIFACT}" == "wheel" ]]; then
197
+ package="$(find release/packages -maxdepth 1 -name '*.whl' -print -quit)"
198
+ else
199
+ package="$(find release/packages -maxdepth 1 -name '*.tar.gz' -print -quit)"
200
+ fi
201
+ [[ -n "${package}" ]]
202
+ python -m venv smoke-venv
203
+ smoke-venv/bin/python -m pip install --upgrade pip
204
+ if [[ "${PROFILE}" == "base" ]]; then
205
+ requirement="ray-hive @ file://$(realpath "${package}")"
206
+ else
207
+ requirement="ray-hive[${PROFILE}] @ file://$(realpath "${package}")"
208
+ fi
209
+ smoke-venv/bin/python -m pip install "${requirement}"
210
+ smoke-venv/bin/python -c 'import ray_hive; print(ray_hive.__all__)'
211
+
212
+ testpypi-publish:
213
+ name: Publish the formal artifact to TestPyPI
214
+ needs: [candidate, build, install-smoke]
215
+ if: needs.candidate.outputs.mode == 'tag' && needs.build.result == 'success' && needs.install-smoke.result == 'success'
216
+ runs-on: ubuntu-latest
217
+ timeout-minutes: 15
218
+ environment: testpypi
219
+ permissions:
220
+ contents: read
221
+ id-token: write
222
+ steps:
223
+ - name: Check out candidate release notes
224
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
225
+ with:
226
+ ref: ${{ needs.candidate.outputs.sha }}
227
+ persist-credentials: false
228
+ - name: Download exact release bundle
229
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
230
+ with:
231
+ artifact-ids: ${{ needs.build.outputs.artifact-id }}
232
+ path: release
233
+ merge-multiple: true
234
+ - name: Verify tag and artifact manifest
235
+ run: |
236
+ python scripts/verify_release_tag.py \
237
+ --tag "${{ needs.candidate.outputs.tag }}" \
238
+ --expected-sha "${{ needs.candidate.outputs.sha }}"
239
+ python scripts/verify_release_artifacts.py release/packages \
240
+ --name ray-hive \
241
+ --version "${{ needs.candidate.outputs.version }}" \
242
+ --manifest release/SHA256SUMS
243
+ - name: Publish to TestPyPI with trusted publishing
244
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
245
+ with:
246
+ repository-url: https://test.pypi.org/legacy/
247
+ packages-dir: release/packages/
248
+
249
+ testpypi-smoke:
250
+ name: TestPyPI install / ${{ matrix.profile }} / Python ${{ matrix.python }}
251
+ needs: [candidate, testpypi-publish]
252
+ if: needs.testpypi-publish.result == 'success'
253
+ runs-on: ubuntu-latest
254
+ timeout-minutes: 15
255
+ strategy:
256
+ fail-fast: false
257
+ matrix:
258
+ python: ["3.12", "3.13"]
259
+ profile: [base, telemetry]
260
+ steps:
261
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
262
+ with:
263
+ python-version: ${{ matrix.python }}
264
+ - name: Install published package from TestPyPI
265
+ env:
266
+ PROFILE: ${{ matrix.profile }}
267
+ VERSION: ${{ needs.candidate.outputs.version }}
268
+ run: |
269
+ set -euo pipefail
270
+ python -m venv smoke-venv
271
+ smoke-venv/bin/python -m pip install --upgrade pip
272
+ if [[ "${PROFILE}" == "base" ]]; then
273
+ requirement="ray-hive==${VERSION}"
274
+ else
275
+ requirement="ray-hive[${PROFILE}]==${VERSION}"
276
+ fi
277
+ for attempt in 1 2 3 4 5; do
278
+ if smoke-venv/bin/python -m pip install --no-cache-dir \
279
+ --index-url https://test.pypi.org/simple/ \
280
+ --extra-index-url https://pypi.org/simple/ "${requirement}"; then
281
+ break
282
+ fi
283
+ [[ "${attempt}" -lt 5 ]] || exit 1
284
+ sleep 15
285
+ done
286
+ smoke-venv/bin/python -c 'import ray_hive; print(ray_hive.__all__)'
287
+
288
+ publish:
289
+ name: Publish the same artifact to PyPI
290
+ needs: [candidate, build, testpypi-smoke]
291
+ if: needs.testpypi-smoke.result == 'success'
292
+ runs-on: ubuntu-latest
293
+ timeout-minutes: 15
294
+ environment: pypi
295
+ permissions:
296
+ contents: read
297
+ id-token: write
298
+ steps:
299
+ - name: Download exact release bundle
300
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
301
+ with:
302
+ artifact-ids: ${{ needs.build.outputs.artifact-id }}
303
+ path: release
304
+ merge-multiple: true
305
+ - name: Publish to PyPI with trusted publishing
306
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
307
+ with:
308
+ packages-dir: release/packages/
309
+
310
+ github-release:
311
+ name: Create the immutable GitHub Release
312
+ needs: [candidate, build, publish]
313
+ if: needs.publish.result == 'success'
314
+ runs-on: ubuntu-latest
315
+ timeout-minutes: 10
316
+ environment: github-release
317
+ permissions:
318
+ contents: write
319
+ steps:
320
+ - name: Check out release notes
321
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
322
+ with:
323
+ ref: ${{ needs.candidate.outputs.sha }}
324
+ persist-credentials: false
325
+ - name: Download exact release bundle
326
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
327
+ with:
328
+ artifact-ids: ${{ needs.build.outputs.artifact-id }}
329
+ path: release
330
+ merge-multiple: true
331
+ - name: Verify artifact manifest before release
332
+ run: >-
333
+ python scripts/verify_release_artifacts.py release/packages
334
+ --name ray-hive
335
+ --version "${{ needs.candidate.outputs.version }}"
336
+ --manifest release/SHA256SUMS
337
+ - name: Create immutable GitHub Release
338
+ env:
339
+ GH_TOKEN: ${{ github.token }}
340
+ run: >-
341
+ gh release create "${{ needs.candidate.outputs.tag }}"
342
+ release/packages/* release/SHA256SUMS release/ray-hive.spdx.json
343
+ --verify-tag
344
+ --title "ray-hive ${{ needs.candidate.outputs.tag }}"
345
+ --notes-file "release-notes/v${{ needs.candidate.outputs.version }}.md"
@@ -0,0 +1,30 @@
1
+ name: Slow integration
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "17 3 * * 0"
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: slow-integration-${{ github.ref }}
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ current-core-evidence:
17
+ name: Current real-infrastructure evidence
18
+ uses: ./.github/workflows/hive-integration.yml
19
+
20
+ scope-notice:
21
+ name: Verify slow-suite scope remains explicit
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 5
24
+ steps:
25
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
26
+ - name: Reject accidental production-ready claims
27
+ run: |
28
+ set -euo pipefail
29
+ ! grep -Eiq 'production[- ]ready|production Core status: supported' README.md
30
+ grep -Fq 'Production Core status requires' docs/conformance.md