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.
- ray_hive-1.0/.gitattributes +3 -0
- ray_hive-1.0/.github/CODEOWNERS +1 -0
- ray_hive-1.0/.github/ISSUE_TEMPLATE/bug.yml +39 -0
- ray_hive-1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- ray_hive-1.0/.github/ISSUE_TEMPLATE/feature.yml +33 -0
- ray_hive-1.0/.github/PULL_REQUEST_TEMPLATE.md +31 -0
- ray_hive-1.0/.github/workflows/ci.yml +147 -0
- ray_hive-1.0/.github/workflows/hive-integration.yml +46 -0
- ray_hive-1.0/.github/workflows/release.yml +345 -0
- ray_hive-1.0/.github/workflows/slow-integration.yml +30 -0
- ray_hive-1.0/.gitignore +14 -0
- ray_hive-1.0/.pre-commit-config.yaml +38 -0
- ray_hive-1.0/CHANGELOG.md +15 -0
- ray_hive-1.0/CONTRIBUTING.md +61 -0
- ray_hive-1.0/LICENSE +201 -0
- ray_hive-1.0/NOTICE +5 -0
- ray_hive-1.0/PKG-INFO +163 -0
- ray_hive-1.0/README.md +122 -0
- ray_hive-1.0/SECURITY.md +36 -0
- ray_hive-1.0/docs/adr/strict-single-query.md +14 -0
- ray_hive-1.0/docs/architecture.md +44 -0
- ray_hive-1.0/docs/compatibility.md +42 -0
- ray_hive-1.0/docs/conformance.md +19 -0
- ray_hive-1.0/docs/consistency.md +25 -0
- ray_hive-1.0/docs/errors.md +28 -0
- ray_hive-1.0/docs/index.md +13 -0
- ray_hive-1.0/docs/security.md +34 -0
- ray_hive-1.0/mkdocs.yml +25 -0
- ray_hive-1.0/pyproject.toml +102 -0
- ray_hive-1.0/release-notes/v1.0.md +32 -0
- ray_hive-1.0/scripts/__init__.py +13 -0
- ray_hive-1.0/scripts/check_license_headers.py +40 -0
- ray_hive-1.0/scripts/check_release.py +67 -0
- ray_hive-1.0/scripts/check_spec.py +137 -0
- ray_hive-1.0/scripts/generate_thrift_stubs.py +122 -0
- ray_hive-1.0/scripts/run_hive_it.sh +44 -0
- ray_hive-1.0/scripts/setup_hive_it.py +117 -0
- ray_hive-1.0/scripts/thrift-compiler.Dockerfile +8 -0
- ray_hive-1.0/scripts/validate_release_candidate.py +140 -0
- ray_hive-1.0/scripts/verify_release_artifacts.py +117 -0
- ray_hive-1.0/scripts/verify_release_tag.py +56 -0
- ray_hive-1.0/spec/hs2-arrow/v1/SPEC_VERSION +1 -0
- ray_hive-1.0/spec/hs2-arrow/v1/capabilities.json +15 -0
- ray_hive-1.0/spec/hs2-arrow/v1/errors.json +17 -0
- ray_hive-1.0/spec/hs2-arrow/v1/expected/primitive-v6.json +12 -0
- ray_hive-1.0/spec/hs2-arrow/v1/fixtures/primitive-v6.json +8 -0
- ray_hive-1.0/spec/hs2-arrow/v1/manifest.json +36 -0
- ray_hive-1.0/spec/hs2-arrow/v1/schema/errors.schema.json +24 -0
- ray_hive-1.0/spec/hs2-arrow/v1/schema/manifest.schema.json +48 -0
- ray_hive-1.0/src/ray_hive/__init__.py +64 -0
- ray_hive-1.0/src/ray_hive/_api.py +40 -0
- ray_hive-1.0/src/ray_hive/_capabilities.py +70 -0
- ray_hive-1.0/src/ray_hive/_compat.py +120 -0
- ray_hive-1.0/src/ray_hive/_credentials.py +140 -0
- ray_hive-1.0/src/ray_hive/_errors.py +157 -0
- ray_hive-1.0/src/ray_hive/_hs2/__init__.py +15 -0
- ray_hive-1.0/src/ray_hive/_hs2/client.py +447 -0
- ray_hive-1.0/src/ray_hive/_hs2/decoder.py +119 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/README.md +19 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/TCLIService-remote +285 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/TCLIService.py +5334 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/__init__.py +1 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/constants.py +72 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/TCLIService/ttypes.py +9014 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/__init__.py +15 -0
- ray_hive-1.0/src/ray_hive/_hs2/generated/idl/TCLIService.thrift +1350 -0
- ray_hive-1.0/src/ray_hive/_hs2/operation.py +120 -0
- ray_hive-1.0/src/ray_hive/_hs2/protocol.py +227 -0
- ray_hive-1.0/src/ray_hive/_hs2/session.py +108 -0
- ray_hive-1.0/src/ray_hive/_hs2/transport.py +275 -0
- ray_hive-1.0/src/ray_hive/_models.py +356 -0
- ray_hive-1.0/src/ray_hive/_planner.py +172 -0
- ray_hive-1.0/src/ray_hive/_schema.py +121 -0
- ray_hive-1.0/src/ray_hive/_sql.py +218 -0
- ray_hive-1.0/src/ray_hive/_task_spec.py +48 -0
- ray_hive-1.0/src/ray_hive/_telemetry.py +25 -0
- ray_hive-1.0/src/ray_hive/_worker.py +323 -0
- ray_hive-1.0/src/ray_hive/datasource.py +90 -0
- ray_hive-1.0/src/ray_hive/py.typed +1 -0
- ray_hive-1.0/src/ray_hive/sql.py +19 -0
- ray_hive-1.0/tests/__init__.py +13 -0
- ray_hive-1.0/tests/_fakes.py +128 -0
- ray_hive-1.0/tests/contract/test_native_protocol_contract.py +250 -0
- ray_hive-1.0/tests/contract/test_spec.py +25 -0
- ray_hive-1.0/tests/integration/docker-compose.yml +28 -0
- ray_hive-1.0/tests/integration/setup.sql +42 -0
- ray_hive-1.0/tests/integration/test_hive_420.py +168 -0
- ray_hive-1.0/tests/unit/test_capabilities_errors.py +88 -0
- ray_hive-1.0/tests/unit/test_client_transport_edges.py +651 -0
- ray_hive-1.0/tests/unit/test_compat_datasource.py +171 -0
- ray_hive-1.0/tests/unit/test_models_credentials.py +215 -0
- ray_hive-1.0/tests/unit/test_operation_planner.py +266 -0
- ray_hive-1.0/tests/unit/test_release.py +74 -0
- ray_hive-1.0/tests/unit/test_schema_decoder.py +186 -0
- ray_hive-1.0/tests/unit/test_session_worker_edges.py +384 -0
- ray_hive-1.0/tests/unit/test_setup_hive_it.py +90 -0
- ray_hive-1.0/tests/unit/test_sql.py +91 -0
- ray_hive-1.0/tests/unit/test_worker.py +297 -0
- ray_hive-1.0/uv.lock +1321 -0
|
@@ -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,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
|