Skip to content

Commit 1c31508

Browse files
authored
ci: add the release pipeline (#58)
* ci: add the release pipeline
1 parent 38d438d commit 1c31508

7 files changed

Lines changed: 539 additions & 2 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Python Publish
2+
3+
on:
4+
release:
5+
types:
6+
- released
7+
pull_request:
8+
paths:
9+
- .github/workflows/python-publish.yml
10+
workflow_dispatch:
11+
inputs:
12+
mode:
13+
description: "dry_run: build & test only, release: build & publish to PyPI"
14+
required: true
15+
default: dry_run
16+
type: choice
17+
options:
18+
- dry_run
19+
- release
20+
21+
jobs:
22+
publish:
23+
runs-on: ubuntu-latest
24+
permissions:
25+
id-token: write
26+
contents: read
27+
env:
28+
CARGO_TERM_COLOR: always
29+
RUSTFLAGS: "-C debuginfo=1"
30+
RUST_BACKTRACE: "1"
31+
CARGO_INCREMENTAL: "0"
32+
steps:
33+
- name: Checkout code
34+
uses: actions/checkout@v4
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.11"
40+
41+
- name: Install Rust toolchain
42+
uses: actions-rust-lang/setup-rust-toolchain@v1
43+
with:
44+
toolchain: stable
45+
cache: false
46+
47+
- name: Install system dependencies
48+
run: |
49+
sudo apt update
50+
sudo apt install -y protobuf-compiler libssl-dev
51+
52+
- name: Install uv
53+
uses: astral-sh/setup-uv@v4
54+
55+
- name: Build distributions
56+
working-directory: python
57+
run: |
58+
make publish
59+
60+
- name: Upload distributions
61+
uses: actions/upload-artifact@v4
62+
with:
63+
name: python-dist
64+
path: python/dist
65+
66+
- name: Publish to PyPI
67+
if: >
68+
(github.event_name == 'release' && github.event.action == 'released') ||
69+
(github.event_name == 'workflow_dispatch' && github.event.inputs.mode == 'release')
70+
working-directory: python
71+
run: |
72+
uv publish --trusted-publishing always

.github/workflows/release.yml

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: Create Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_type:
7+
description: 'Version bump type (patch/minor/major bumps version, current keeps it unchanged)'
8+
required: true
9+
default: 'patch'
10+
type: choice
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
- current
16+
release_channel:
17+
description: 'Release channel (preview creates beta tag, stable creates release tag)'
18+
required: true
19+
default: 'preview'
20+
type: choice
21+
options:
22+
- preview
23+
- stable
24+
dry_run:
25+
description: 'Dry run (simulate the release without pushing)'
26+
required: true
27+
default: true
28+
type: boolean
29+
30+
jobs:
31+
create-release:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- name: Output Inputs
35+
run: echo "${{ toJSON(github.event.inputs) }}"
36+
37+
- name: Checkout repository
38+
uses: actions/checkout@v4
39+
with:
40+
ref: main
41+
token: ${{ secrets.GITHUB_TOKEN }}
42+
fetch-depth: 0
43+
44+
- name: Set up Python
45+
uses: actions/setup-python@v5
46+
with:
47+
python-version: '3.11'
48+
49+
- name: Install uv
50+
uses: astral-sh/setup-uv@v4
51+
52+
- name: Install python dependencies
53+
run: |
54+
pip install packaging bump-my-version toml
55+
56+
- name: Install dependencies
57+
run: |
58+
sudo apt update
59+
sudo apt install -y protobuf-compiler libssl-dev
60+
61+
- uses: actions-rust-lang/setup-rust-toolchain@v1
62+
with:
63+
toolchain: stable
64+
components: rustfmt, clippy
65+
cache: false
66+
67+
- uses: rui314/setup-mold@v1
68+
69+
- name: Get current version
70+
id: current_version
71+
run: |
72+
CURRENT_VERSION=$(python -c "import toml; print(toml.load('.bumpversion.toml')['tool']['bumpversion']['current_version'])")
73+
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
74+
echo "Current version: $CURRENT_VERSION"
75+
76+
- name: Calculate base version
77+
id: base_version
78+
run: |
79+
python ci/calculate_version.py \
80+
--current "${{ steps.current_version.outputs.version }}" \
81+
--type "${{ inputs.release_type }}" \
82+
--channel "${{ inputs.release_channel }}"
83+
84+
- name: Determine tag and version
85+
id: versions
86+
run: |
87+
BASE_VERSION="${{ steps.base_version.outputs.version }}"
88+
if [ "${{ inputs.release_channel }}" == "stable" ]; then
89+
TAG="v${BASE_VERSION}"
90+
VERSION="${BASE_VERSION}"
91+
else
92+
# For preview releases, find the next beta number for this base version
93+
BETA_TAGS=$(git tag -l "v${BASE_VERSION}-beta.*" | sort -V)
94+
if [ -z "$BETA_TAGS" ]; then
95+
BETA_NUM=1
96+
else
97+
LAST_BETA=$(echo "$BETA_TAGS" | tail -n 1)
98+
LAST_NUM=$(echo "$LAST_BETA" | sed "s/v${BASE_VERSION}-beta.//")
99+
BETA_NUM=$((LAST_NUM + 1))
100+
fi
101+
TAG="v${BASE_VERSION}-beta.${BETA_NUM}"
102+
VERSION="${BASE_VERSION}-beta.${BETA_NUM}"
103+
fi
104+
105+
echo "tag=$TAG" >> $GITHUB_OUTPUT
106+
echo "version=$VERSION" >> $GITHUB_OUTPUT
107+
echo "Tag will be: $TAG"
108+
echo "Version will be: $VERSION"
109+
110+
- name: Update version (when version changes)
111+
if: inputs.release_type != 'current'
112+
run: |
113+
python ci/bump_version.py --version "${{ steps.versions.outputs.version }}"
114+
115+
- name: Configure git identity
116+
run: |
117+
git config user.name 'Lance Release Bot'
118+
git config user.email 'dev@lancedb.com'
119+
120+
- name: Update Cargo lock version (when version changes)
121+
if: inputs.release_type != 'current'
122+
run: |
123+
cargo check --manifest-path rust/lance-graph/Cargo.toml
124+
cargo check --manifest-path python/Cargo.toml
125+
126+
- name: Create release commit (when version changes)
127+
if: inputs.release_type != 'current'
128+
run: |
129+
git add -A
130+
git commit -m "chore: release version ${{ steps.versions.outputs.version }}" || echo "No changes to commit"
131+
132+
- name: Create tag
133+
run: |
134+
git tag -a "${{ steps.versions.outputs.tag }}" -m "Release ${{ steps.versions.outputs.tag }}"
135+
136+
- name: Push changes (if not dry run)
137+
if: ${{ !inputs.dry_run }}
138+
env:
139+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
140+
run: |
141+
# Configure git to use the token for authentication
142+
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git"
143+
144+
if [ "${{ inputs.release_type }}" != "current" ]; then
145+
# Push the version bump commit
146+
git push origin main
147+
fi
148+
# Always push the tag
149+
git push origin "${{ steps.versions.outputs.tag }}"
150+
151+
- name: Create GitHub Release Draft (if not dry run)
152+
if: ${{ !inputs.dry_run }}
153+
uses: softprops/action-gh-release@v2
154+
with:
155+
tag_name: ${{ steps.versions.outputs.tag }}
156+
name: ${{ steps.versions.outputs.tag }}
157+
generate_release_notes: true
158+
draft: true
159+
prerelease: ${{ inputs.release_channel == 'preview' }}
160+
token: ${{ secrets.GITHUB_TOKEN }}
161+
162+
- name: Summary
163+
run: |
164+
echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
165+
echo "" >> $GITHUB_STEP_SUMMARY
166+
echo "- **Release Type:** ${{ inputs.release_type }}" >> $GITHUB_STEP_SUMMARY
167+
echo "- **Release Channel:** ${{ inputs.release_channel }}" >> $GITHUB_STEP_SUMMARY
168+
echo "- **Current Version:** ${{ steps.current_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
169+
if [ "${{ inputs.release_type }}" != "current" ]; then
170+
echo "- **New Version:** ${{ steps.versions.outputs.version }}" >> $GITHUB_STEP_SUMMARY
171+
fi
172+
echo "- **Tag:** ${{ steps.versions.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
173+
echo "- **Dry Run:** ${{ inputs.dry_run }}" >> $GITHUB_STEP_SUMMARY
174+
175+
if [ "${{ inputs.dry_run }}" == "true" ]; then
176+
echo "" >> $GITHUB_STEP_SUMMARY
177+
echo "⚠️ This was a dry run. No changes were pushed." >> $GITHUB_STEP_SUMMARY
178+
else
179+
echo "" >> $GITHUB_STEP_SUMMARY
180+
echo "📝 Draft release created successfully!" >> $GITHUB_STEP_SUMMARY
181+
echo "" >> $GITHUB_STEP_SUMMARY
182+
echo "### Next Steps:" >> $GITHUB_STEP_SUMMARY
183+
echo "1. Review the draft release on the [releases page](https://github.com/${{ github.repository }}/releases)" >> $GITHUB_STEP_SUMMARY
184+
echo "2. Edit the release notes if needed" >> $GITHUB_STEP_SUMMARY
185+
echo "3. Publish the release to trigger automatic publishing to PyPI and crates.io" >> $GITHUB_STEP_SUMMARY
186+
fi

.github/workflows/rust-publish.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Rust Publish
2+
3+
on:
4+
release:
5+
types:
6+
- released
7+
pull_request:
8+
paths:
9+
- .github/workflows/rust-publish.yml
10+
workflow_dispatch:
11+
inputs:
12+
mode:
13+
description: "dry_run: build & test only, release: build & publish to crates.io"
14+
required: true
15+
default: dry_run
16+
type: choice
17+
options:
18+
- dry_run
19+
- release
20+
21+
env:
22+
CARGO_TERM_COLOR: always
23+
RUSTFLAGS: "-C debuginfo=1"
24+
RUST_BACKTRACE: "1"
25+
CARGO_INCREMENTAL: "0"
26+
CARGO_BUILD_JOBS: "1"
27+
28+
jobs:
29+
publish:
30+
runs-on: ubuntu-24.04
31+
timeout-minutes: 60
32+
steps:
33+
- name: Checkout code
34+
uses: actions/checkout@v4
35+
36+
- name: Install dependencies
37+
run: |
38+
sudo apt update
39+
sudo apt install -y protobuf-compiler libssl-dev
40+
41+
- uses: actions-rust-lang/setup-rust-toolchain@v1
42+
with:
43+
toolchain: stable
44+
components: rustfmt, clippy
45+
cache: false
46+
47+
- uses: rui314/setup-mold@v1
48+
49+
- uses: katyo/publish-crates@v2
50+
with:
51+
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
52+
args: "--all-features"
53+
path: rust/lance-graph
54+
dry-run: ${{ github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && github.event.inputs.mode == 'dry_run') }}

0 commit comments

Comments
 (0)