Skip to content

Commit b158f94

Browse files
committed
Add tagging/release method
Signed-off-by: Adam Gutglick <adam@spiraldb.com>
1 parent 6551373 commit b158f94

10 files changed

Lines changed: 495 additions & 1 deletion

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
name: CI and Release Tag
5+
6+
on:
7+
pull_request:
8+
push:
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
ci:
18+
name: CI
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v6
23+
24+
- name: Install Rust
25+
uses: dtolnay/rust-toolchain@stable
26+
with:
27+
components: rustfmt
28+
29+
- name: Cache Rust dependencies
30+
uses: Swatinem/rust-cache@v2
31+
32+
- name: Install cargo-nextest
33+
uses: taiki-e/install-action@v2
34+
with:
35+
tool: nextest
36+
37+
- name: Check formatting
38+
run: cargo fmt --check
39+
40+
- name: Check build
41+
run: cargo check --locked
42+
43+
- name: Run tests
44+
run: cargo nextest run --locked
45+
46+
release-tag:
47+
name: Release Tag
48+
needs: ci
49+
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.deleted == false
50+
runs-on: ubuntu-latest
51+
permissions:
52+
contents: write
53+
steps:
54+
- name: Checkout
55+
uses: actions/checkout@v6
56+
with:
57+
fetch-depth: 0
58+
fetch-tags: true
59+
60+
- name: Compare release dependency versions
61+
id: versions
62+
shell: bash
63+
env:
64+
BEFORE: ${{ github.event.before }}
65+
run: |
66+
set -euo pipefail
67+
68+
zero_sha="0000000000000000000000000000000000000000"
69+
if [[ "${BEFORE}" != "${zero_sha}" ]] && ! git cat-file -e "${BEFORE}^{commit}" 2>/dev/null; then
70+
git fetch --no-tags --depth=1 origin "${BEFORE}" || true
71+
fi
72+
73+
if [[ "${BEFORE}" == "${zero_sha}" ]] || ! git cat-file -e "${BEFORE}:Cargo.lock" 2>/dev/null; then
74+
tag="$(python3 scripts/version_pair.py tag)"
75+
echo "initial release tag: ${tag}"
76+
{
77+
echo "release_needed=true"
78+
echo "old_tag="
79+
echo "new_tag=${tag}"
80+
echo "changes=initial"
81+
} >> "$GITHUB_OUTPUT"
82+
else
83+
git show "${BEFORE}:Cargo.lock" > /tmp/previous-Cargo.lock
84+
python3 scripts/version_pair.py changed \
85+
--old /tmp/previous-Cargo.lock \
86+
--new Cargo.lock \
87+
--github-output "$GITHUB_OUTPUT"
88+
fi
89+
90+
- name: Create release tag
91+
if: steps.versions.outputs.release_needed == 'true'
92+
shell: bash
93+
env:
94+
TAG: ${{ steps.versions.outputs.new_tag }}
95+
run: |
96+
set -euo pipefail
97+
98+
head_commit="$(git rev-parse HEAD)"
99+
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
100+
tag_commit="$(git rev-list -n 1 "${TAG}")"
101+
if [[ "${tag_commit}" == "${head_commit}" ]]; then
102+
echo "Tag ${TAG} already exists at HEAD."
103+
exit 0
104+
fi
105+
106+
echo "Tag ${TAG} already exists at ${tag_commit}, not HEAD ${head_commit}." >&2
107+
exit 1
108+
fi
109+
110+
git tag "${TAG}"
111+
git push origin "refs/tags/${TAG}"

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ In the future we hope we can minimize the amount of identical code, but for the
1111

1212
## Versioning
1313

14-
For each update of Apache DataFusion or Vortex, we'll want to create a new tag `<vortex-version>-<df-version>` so we can check every support version combination of both tools.
14+
Release tags use the format `<vortex-version>-<df-version>`, where `vortex-version` is the resolved `vortex-datafusion` crate version and `df-version` is the resolved `datafusion`/`datafusion-cli` crate version.
15+
16+
Merges to `main` create a tag only when `Cargo.lock` changes either of those resolved versions. Code, docs, or unrelated dependency changes still run CI, but do not create release tags.
17+
18+
[Renovate](https://docs.renovatebot.com/) updates Cargo manifests, `Cargo.lock`, and GitHub Actions workflow action versions. DataFusion and DataFusion CLI updates are grouped together so they continue to resolve to the same version.

REUSE.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ precedence = "override"
66
SPDX-FileCopyrightText = "Copyright the Vortex contributors"
77
SPDX-License-Identifier = "Apache-2.0"
88

9+
[[annotations]]
10+
path = "renovate.json"
11+
precedence = "override"
12+
SPDX-FileCopyrightText = "Copyright the Vortex contributors"
13+
SPDX-License-Identifier = "Apache-2.0"
14+
915
[[annotations]]
1016
path = "NOTICE"
1117
precedence = "override"

renovate.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3+
"extends": [
4+
"config:recommended"
5+
],
6+
"enabledManagers": [
7+
"cargo",
8+
"github-actions"
9+
],
10+
"rangeStrategy": "bump",
11+
"lockFileMaintenance": {
12+
"enabled": true
13+
},
14+
"packageRules": [
15+
{
16+
"matchManagers": [
17+
"cargo"
18+
],
19+
"matchPackageNames": [
20+
"datafusion",
21+
"datafusion-cli"
22+
],
23+
"groupName": "DataFusion Rust crates"
24+
},
25+
{
26+
"matchManagers": [
27+
"cargo"
28+
],
29+
"matchPackageNames": [
30+
"vortex-datafusion"
31+
],
32+
"groupName": "Vortex DataFusion"
33+
}
34+
]
35+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
version = 4
5+
6+
[[package]]
7+
name = "datafusion"
8+
version = "54.0.0"
9+
10+
[[package]]
11+
name = "datafusion-cli"
12+
version = "54.0.0"
13+
14+
[[package]]
15+
name = "vortex-datafusion"
16+
version = "0.70.0"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
version = 4
5+
6+
[[package]]
7+
name = "datafusion"
8+
version = "53.1.0"
9+
10+
[[package]]
11+
name = "datafusion-cli"
12+
version = "53.1.0"
13+
14+
[[package]]
15+
name = "vortex-datafusion"
16+
version = "0.69.0"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
version = 4
5+
6+
[[package]]
7+
name = "datafusion"
8+
version = "53.1.0"
9+
10+
[[package]]
11+
name = "datafusion-cli"
12+
version = "54.0.0"
13+
14+
[[package]]
15+
name = "vortex-datafusion"
16+
version = "0.69.0"

scripts/test_version_pair.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: Apache-2.0
3+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
4+
5+
from __future__ import annotations
6+
7+
from pathlib import Path
8+
import subprocess
9+
import sys
10+
import tempfile
11+
import unittest
12+
13+
14+
SCRIPT = Path(__file__).with_name("version_pair.py")
15+
FIXTURES = Path(__file__).parent / "fixtures" / "version_pair"
16+
17+
18+
class VersionPairCliTest(unittest.TestCase):
19+
def test_tag_and_mismatched_datafusion_versions(self) -> None:
20+
result = self.run_script("tag", "--lockfile", fixture("current.lock"))
21+
22+
self.assertEqual(result.returncode, 0, result.stderr)
23+
self.assertEqual(result.stdout.strip(), "0.69.0-53.1.0")
24+
25+
result = self.run_script("tag", "--lockfile", fixture("mismatched.lock"))
26+
27+
self.assertNotEqual(result.returncode, 0)
28+
self.assertIn("resolves datafusion 53.1.0", result.stderr)
29+
self.assertIn("datafusion-cli 54.0.0", result.stderr)
30+
31+
def test_changed_lockfiles(self) -> None:
32+
result = self.run_script(
33+
"changed",
34+
"--old",
35+
fixture("current.lock"),
36+
"--new",
37+
fixture("current.lock"),
38+
)
39+
40+
self.assertEqual(result.returncode, 0, result.stderr)
41+
self.assertIn("no release needed", result.stdout)
42+
43+
with tempfile.NamedTemporaryFile() as output:
44+
result = self.run_script(
45+
"changed",
46+
"--old",
47+
fixture("current.lock"),
48+
"--new",
49+
fixture("both-changed.lock"),
50+
"--github-output",
51+
output.name,
52+
)
53+
output.seek(0)
54+
github_output = output.read().decode("utf-8")
55+
56+
self.assertEqual(result.returncode, 0, result.stderr)
57+
self.assertIn("release needed", result.stdout)
58+
self.assertIn("release_needed=true\n", github_output)
59+
self.assertIn("old_tag=0.69.0-53.1.0\n", github_output)
60+
self.assertIn("new_tag=0.70.0-54.0.0\n", github_output)
61+
self.assertIn("changes=vortex-datafusion,datafusion/datafusion-cli\n", github_output)
62+
63+
def run_script(self, *args: str) -> subprocess.CompletedProcess[str]:
64+
return subprocess.run(
65+
[sys.executable, str(SCRIPT), *args],
66+
check=False,
67+
text=True,
68+
capture_output=True,
69+
)
70+
71+
72+
def fixture(name: str) -> str:
73+
return str(FIXTURES / name)
74+
75+
76+
if __name__ == "__main__":
77+
unittest.main()

0 commit comments

Comments
 (0)