rapsqlite 0.0.1__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.
@@ -0,0 +1,109 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on ${{ matrix.os }}
12
+ runs-on: ${{ matrix.os }}
13
+ strategy:
14
+ matrix:
15
+ os: [ubuntu-latest, macos-latest, windows-latest]
16
+ python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install Rust
27
+ uses: actions-rs/toolchain@v1
28
+ with:
29
+ toolchain: stable
30
+ override: true
31
+
32
+ - name: Install maturin
33
+ run: pip install maturin
34
+
35
+ - name: Build package (Linux)
36
+ if: runner.os == 'Linux'
37
+ run: python -m maturin build --release --skip-auditwheel
38
+
39
+ - name: Build package (macOS/Windows)
40
+ if: runner.os != 'Linux'
41
+ run: python -m maturin build --release
42
+
43
+ - name: Install package
44
+ shell: bash
45
+ run: pip install target/wheels/rapsqlite-*.whl --force-reinstall
46
+
47
+ - name: Test package import
48
+ shell: bash
49
+ run: |
50
+ python -c "import rapsqlite; print('Version:', rapsqlite.__version__)"
51
+
52
+ lint:
53
+ name: Lint
54
+ runs-on: ubuntu-latest
55
+ steps:
56
+ - uses: actions/checkout@v4
57
+
58
+ - name: Set up Rust
59
+ uses: actions-rs/toolchain@v1
60
+ with:
61
+ toolchain: stable
62
+ components: clippy, rustfmt
63
+ override: true
64
+
65
+ - name: Run clippy
66
+ run: cargo clippy --lib -- -D clippy::all -A deprecated
67
+
68
+ - name: Check formatting
69
+ run: cargo fmt -- --check
70
+
71
+ build-wheels:
72
+ name: Build wheels on ${{ matrix.os }}
73
+ runs-on: ${{ matrix.os }}
74
+ strategy:
75
+ matrix:
76
+ os: [ubuntu-latest, macos-latest, windows-latest]
77
+
78
+ steps:
79
+ - uses: actions/checkout@v4
80
+
81
+ - name: Set up Python
82
+ uses: actions/setup-python@v5
83
+ with:
84
+ python-version: '3.12'
85
+
86
+ - name: Install Rust
87
+ uses: actions-rs/toolchain@v1
88
+ with:
89
+ toolchain: stable
90
+ override: true
91
+
92
+ - name: Install maturin
93
+ run: pip install maturin
94
+
95
+ - name: Build wheels (Linux with manylinux)
96
+ if: matrix.os == 'ubuntu-latest'
97
+ run: |
98
+ docker run --rm -v "${{ github.workspace }}":/io -w /io ghcr.io/pyo3/maturin:main build --release --out dist --manylinux manylinux_2_24
99
+
100
+ - name: Build wheels (macOS/Windows)
101
+ if: matrix.os != 'ubuntu-latest'
102
+ run: maturin build --release --out dist
103
+
104
+ - name: Upload wheels
105
+ uses: actions/upload-artifact@v4
106
+ with:
107
+ name: wheels-${{ matrix.os }}
108
+ path: dist
109
+
@@ -0,0 +1,120 @@
1
+ name: Publish Existing Wheels + Rebuild Sdist
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ run_id:
7
+ description: 'GitHub Actions Run ID containing the wheel artifacts to use'
8
+ required: true
9
+ type: string
10
+
11
+ env:
12
+ MATURIN_PROFILE: release
13
+
14
+ jobs:
15
+ publish-existing-rebuild-sdist:
16
+ name: Publish Existing Wheels + Rebuild Sdist
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ actions: read
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+
30
+ - name: Set up Rust
31
+ uses: dtolnay/rust-toolchain@stable
32
+
33
+ - name: Install build tooling
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ pip install maturin
37
+
38
+ - name: Build sdist (with fixed metadata)
39
+ run: maturin sdist --out dist
40
+
41
+ - name: Download all wheel artifacts from existing run
42
+ uses: actions/download-artifact@v4
43
+ with:
44
+ run-id: ${{ inputs.run_id }}
45
+ pattern: wheel-*
46
+ merge-multiple: true
47
+ path: artifacts/wheels
48
+ github-token: ${{ secrets.GITHUB_TOKEN }}
49
+
50
+ - name: Combine artifacts
51
+ shell: bash
52
+ run: |
53
+ set -e
54
+
55
+ # Copy wheels from artifacts directory
56
+ echo "=== Copying wheels ==="
57
+ find artifacts -name "*.whl" -type f -exec cp -v {} dist/ \; || true
58
+
59
+ # Verify we have files
60
+ echo ""
61
+ echo "=== Final dist contents ==="
62
+ ls -lah dist/ || echo "dist/ is empty or doesn't exist"
63
+ echo ""
64
+ echo "=== Distribution files ==="
65
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) 2>/dev/null | sort || echo "No files found"
66
+ echo ""
67
+
68
+ # Count files
69
+ WHEEL_COUNT=$(find dist -name "*.whl" -type f 2>/dev/null | wc -l || echo "0")
70
+ SDIST_COUNT=$(find dist -name "*.tar.gz" -type f 2>/dev/null | wc -l || echo "0")
71
+ echo "Wheels: $WHEEL_COUNT"
72
+ echo "Source distributions: $SDIST_COUNT"
73
+
74
+ if [ "$WHEEL_COUNT" -eq 0 ] || [ "$SDIST_COUNT" -eq 0 ]; then
75
+ echo "ERROR: Missing distribution files!"
76
+ echo "Wheels found: $WHEEL_COUNT"
77
+ echo "Source distributions found: $SDIST_COUNT"
78
+ exit 1
79
+ fi
80
+
81
+ echo "✅ Successfully prepared $((WHEEL_COUNT + SDIST_COUNT)) distribution files"
82
+
83
+ - name: Publish to PyPI
84
+ env:
85
+ TWINE_USERNAME: __token__
86
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
87
+ run: |
88
+ set -e
89
+ pip install twine
90
+
91
+ # Check if we have files to upload
92
+ echo "=== Files to upload ==="
93
+ ls -lah dist/
94
+ echo ""
95
+
96
+ # Verify token is set (without exposing it)
97
+ if [ -z "$TWINE_PASSWORD" ]; then
98
+ echo "ERROR: PYPI_API_TOKEN secret is not set!"
99
+ exit 1
100
+ fi
101
+
102
+ echo "✅ PyPI token is configured"
103
+ echo ""
104
+
105
+ # Upload with verbose output for debugging
106
+ echo "=== Uploading to PyPI ==="
107
+ twine upload dist/* --verbose || {
108
+ echo ""
109
+ echo "❌ Upload failed. Common issues:"
110
+ echo " 1. Package version already exists on PyPI"
111
+ echo " 2. Invalid or expired PyPI API token"
112
+ echo " 3. Network/authentication error"
113
+ echo ""
114
+ echo "Check PyPI: https://pypi.org/project/rapsqlite/"
115
+ exit 1
116
+ }
117
+
118
+ echo ""
119
+ echo "✅ Successfully published to PyPI!"
120
+
@@ -0,0 +1,122 @@
1
+ name: Publish Existing Artifacts to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ run_id:
7
+ description: 'GitHub Actions Run ID containing the artifacts to publish'
8
+ required: true
9
+ type: string
10
+
11
+ env:
12
+ MATURIN_PROFILE: release
13
+
14
+ jobs:
15
+ publish-existing:
16
+ name: Publish Existing Artifacts to PyPI
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ actions: read
21
+ steps:
22
+ - name: Download all wheel artifacts from run
23
+ uses: actions/download-artifact@v4
24
+ with:
25
+ run-id: ${{ inputs.run_id }}
26
+ pattern: wheel-*
27
+ merge-multiple: true
28
+ path: artifacts/wheels
29
+ github-token: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Download sdist artifact from run
32
+ uses: actions/download-artifact@v4
33
+ with:
34
+ run-id: ${{ inputs.run_id }}
35
+ pattern: sdist
36
+ merge-multiple: true
37
+ path: artifacts/sdist
38
+ github-token: ${{ secrets.GITHUB_TOKEN }}
39
+
40
+ - name: Combine artifacts
41
+ shell: bash
42
+ run: |
43
+ set -e
44
+
45
+ # Debug: Show what we downloaded
46
+ echo "=== Artifacts structure ==="
47
+ find artifacts -type f -o -type d 2>/dev/null | sort || true
48
+ echo ""
49
+
50
+ # Create clean dist directory
51
+ mkdir -p dist
52
+
53
+ # Copy wheels from artifacts directory (handle all possible structures)
54
+ echo "=== Copying wheels ==="
55
+ find artifacts -name "*.whl" -type f -exec cp -v {} dist/ \; || true
56
+
57
+ # Copy sdist from artifacts directory (handle all possible structures)
58
+ echo "=== Copying sdist ==="
59
+ find artifacts -name "*.tar.gz" -type f -exec cp -v {} dist/ \; || true
60
+
61
+ # Verify we have files
62
+ echo ""
63
+ echo "=== Final dist contents ==="
64
+ ls -lah dist/ || echo "dist/ is empty or doesn't exist"
65
+ echo ""
66
+ echo "=== Distribution files ==="
67
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) 2>/dev/null | sort || echo "No files found"
68
+ echo ""
69
+
70
+ # Count files
71
+ WHEEL_COUNT=$(find dist -name "*.whl" -type f 2>/dev/null | wc -l || echo "0")
72
+ SDIST_COUNT=$(find dist -name "*.tar.gz" -type f 2>/dev/null | wc -l || echo "0")
73
+ echo "Wheels: $WHEEL_COUNT"
74
+ echo "Source distributions: $SDIST_COUNT"
75
+
76
+ if [ "$WHEEL_COUNT" -eq 0 ] && [ "$SDIST_COUNT" -eq 0 ]; then
77
+ echo "ERROR: No distribution files found in dist/!"
78
+ echo "Checking artifacts directory:"
79
+ find artifacts -type f 2>/dev/null || true
80
+ exit 1
81
+ fi
82
+
83
+ echo "✅ Successfully prepared $((WHEEL_COUNT + SDIST_COUNT)) distribution files"
84
+
85
+ - name: Publish to PyPI
86
+ env:
87
+ TWINE_USERNAME: __token__
88
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
89
+ run: |
90
+ set -e
91
+ pip install twine
92
+
93
+ # Check if we have files to upload
94
+ echo "=== Files to upload ==="
95
+ ls -lah dist/
96
+ echo ""
97
+
98
+ # Verify token is set (without exposing it)
99
+ if [ -z "$TWINE_PASSWORD" ]; then
100
+ echo "ERROR: PYPI_API_TOKEN secret is not set!"
101
+ exit 1
102
+ fi
103
+
104
+ echo "✅ PyPI token is configured"
105
+ echo ""
106
+
107
+ # Upload with verbose output for debugging
108
+ echo "=== Uploading to PyPI ==="
109
+ twine upload dist/* --verbose || {
110
+ echo ""
111
+ echo "❌ Upload failed. Common issues:"
112
+ echo " 1. Package version already exists on PyPI"
113
+ echo " 2. Invalid or expired PyPI API token"
114
+ echo " 3. Network/authentication error"
115
+ echo ""
116
+ echo "Check PyPI: https://pypi.org/project/rapsqlite/"
117
+ exit 1
118
+ }
119
+
120
+ echo ""
121
+ echo "✅ Successfully published to PyPI!"
122
+
@@ -0,0 +1,333 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*' # Triggers on version tags like v0.1.0, v1.0.0, etc.
7
+
8
+ env:
9
+ MATURIN_PROFILE: release
10
+
11
+ jobs:
12
+ build-wheels:
13
+ name: Build wheels (${{ matrix.os }} / ${{ matrix.architecture }} / py${{ matrix.python }})
14
+ runs-on: ${{ matrix.os }}
15
+ permissions:
16
+ contents: read
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ include:
21
+ # Ubuntu x86-64
22
+ - os: ubuntu-latest
23
+ python: "3.8"
24
+ architecture: x86-64
25
+ - os: ubuntu-latest
26
+ python: "3.9"
27
+ architecture: x86-64
28
+ - os: ubuntu-latest
29
+ python: "3.10"
30
+ architecture: x86-64
31
+ - os: ubuntu-latest
32
+ python: "3.11"
33
+ architecture: x86-64
34
+ - os: ubuntu-latest
35
+ python: "3.12"
36
+ architecture: x86-64
37
+ - os: ubuntu-latest
38
+ python: "3.13"
39
+ architecture: x86-64
40
+ # Ubuntu ARM64 (aarch64)
41
+ - os: ubuntu-latest
42
+ python: "3.8"
43
+ architecture: aarch64
44
+ - os: ubuntu-latest
45
+ python: "3.9"
46
+ architecture: aarch64
47
+ - os: ubuntu-latest
48
+ python: "3.10"
49
+ architecture: aarch64
50
+ - os: ubuntu-latest
51
+ python: "3.11"
52
+ architecture: aarch64
53
+ - os: ubuntu-latest
54
+ python: "3.12"
55
+ architecture: aarch64
56
+ - os: ubuntu-latest
57
+ python: "3.13"
58
+ architecture: aarch64
59
+ # macOS latest (typically arm64/Apple Silicon)
60
+ - os: macos-latest
61
+ python: "3.8"
62
+ architecture: aarch64
63
+ - os: macos-latest
64
+ python: "3.9"
65
+ architecture: aarch64
66
+ - os: macos-latest
67
+ python: "3.10"
68
+ architecture: aarch64
69
+ - os: macos-latest
70
+ python: "3.11"
71
+ architecture: aarch64
72
+ - os: macos-latest
73
+ python: "3.12"
74
+ architecture: aarch64
75
+ - os: macos-latest
76
+ python: "3.13"
77
+ architecture: aarch64
78
+ # Windows x86-64
79
+ - os: windows-latest
80
+ python: "3.8"
81
+ architecture: x86-64
82
+ - os: windows-latest
83
+ python: "3.9"
84
+ architecture: x86-64
85
+ - os: windows-latest
86
+ python: "3.10"
87
+ architecture: x86-64
88
+ - os: windows-latest
89
+ python: "3.11"
90
+ architecture: x86-64
91
+ - os: windows-latest
92
+ python: "3.12"
93
+ architecture: x86-64
94
+ - os: windows-latest
95
+ python: "3.13"
96
+ architecture: x86-64
97
+ # macOS 15 Intel (x86-64)
98
+ - os: macos-15-intel
99
+ python: "3.8"
100
+ architecture: x86-64
101
+ - os: macos-15-intel
102
+ python: "3.9"
103
+ architecture: x86-64
104
+ - os: macos-15-intel
105
+ python: "3.10"
106
+ architecture: x86-64
107
+ - os: macos-15-intel
108
+ python: "3.11"
109
+ architecture: x86-64
110
+ - os: macos-15-intel
111
+ python: "3.12"
112
+ architecture: x86-64
113
+ - os: macos-15-intel
114
+ python: "3.13"
115
+ architecture: x86-64
116
+ # Windows 11 ARM (aarch64)
117
+ - os: windows-11-arm
118
+ python: "3.11"
119
+ architecture: aarch64
120
+ - os: windows-11-arm
121
+ python: "3.12"
122
+ architecture: aarch64
123
+ - os: windows-11-arm
124
+ python: "3.13"
125
+ architecture: aarch64
126
+ steps:
127
+ - name: Checkout repository
128
+ uses: actions/checkout@v4
129
+
130
+ - name: Set up QEMU
131
+ if: matrix.os == 'ubuntu-latest' && matrix.architecture == 'aarch64'
132
+ uses: docker/setup-qemu-action@v3
133
+ with:
134
+ platforms: arm64
135
+
136
+ - name: Build wheel (Linux - manylinux)
137
+ if: matrix.os == 'ubuntu-latest'
138
+ env:
139
+ PYO3_USE_ABI3_FORWARD_COMPATIBILITY: ${{ (matrix.python == '3.13') && '1' || '' }}
140
+ run: |
141
+ PYTHON_VER="${{ matrix.python }}"
142
+ PYTHON_TAG="cp${PYTHON_VER//./}"
143
+ if [ "${{ matrix.architecture }}" = "aarch64" ]; then
144
+ DOCKER_IMAGE="quay.io/pypa/manylinux_2_28_aarch64:latest"
145
+ else
146
+ DOCKER_IMAGE="quay.io/pypa/manylinux_2_28_x86_64:latest"
147
+ fi
148
+ docker run --rm \
149
+ --platform linux/${{ matrix.architecture }} \
150
+ -v "$PWD:/io" \
151
+ -e PYO3_USE_ABI3_FORWARD_COMPATIBILITY="${{ (matrix.python == '3.13') && '1' || '' }}" \
152
+ -e PYTHON_TAG="${PYTHON_TAG}" \
153
+ -w /io \
154
+ ${DOCKER_IMAGE} \
155
+ /bin/bash -c "
156
+ curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --profile minimal
157
+ source \$HOME/.cargo/env
158
+ /opt/python/\${PYTHON_TAG}-\${PYTHON_TAG}/bin/pip install maturin
159
+ /opt/python/\${PYTHON_TAG}-\${PYTHON_TAG}/bin/python -m maturin build \
160
+ --out dist \
161
+ --strip \
162
+ --release \
163
+ --manylinux 2_28 \
164
+ --interpreter /opt/python/\${PYTHON_TAG}-\${PYTHON_TAG}/bin/python
165
+ "
166
+
167
+ - name: Set up Python ${{ matrix.python }} (macOS/Windows)
168
+ if: matrix.os != 'ubuntu-latest'
169
+ uses: actions/setup-python@v5
170
+ with:
171
+ python-version: ${{ matrix.python }}
172
+
173
+ - name: Set up Rust (macOS/Windows)
174
+ if: matrix.os != 'ubuntu-latest'
175
+ uses: dtolnay/rust-toolchain@stable
176
+
177
+ - name: Install build tooling (macOS/Windows)
178
+ if: matrix.os != 'ubuntu-latest'
179
+ run: |
180
+ python -m pip install --upgrade pip
181
+ pip install maturin
182
+
183
+ - name: Build wheel (macOS/Windows)
184
+ if: matrix.os != 'ubuntu-latest'
185
+ env:
186
+ PYO3_USE_ABI3_FORWARD_COMPATIBILITY: ${{ (matrix.python == '3.13') && '1' || '' }}
187
+ run: maturin build --out dist --strip --release
188
+
189
+ - name: Upload wheel artifact
190
+ uses: actions/upload-artifact@v4
191
+ with:
192
+ name: wheel-${{ matrix.os }}-${{ matrix.architecture }}-py${{ matrix.python }}
193
+ path: dist/*.whl
194
+ if-no-files-found: error
195
+ retention-days: 7
196
+
197
+ build-sdist:
198
+ name: Build source distribution
199
+ runs-on: ubuntu-latest
200
+ permissions:
201
+ contents: read
202
+ steps:
203
+ - name: Checkout repository
204
+ uses: actions/checkout@v4
205
+
206
+ - name: Set up Python
207
+ uses: actions/setup-python@v5
208
+ with:
209
+ python-version: "3.12"
210
+
211
+ - name: Set up Rust
212
+ uses: dtolnay/rust-toolchain@stable
213
+
214
+ - name: Install build tooling
215
+ run: |
216
+ python -m pip install --upgrade pip
217
+ pip install maturin
218
+
219
+ - name: Build sdist
220
+ run: maturin sdist --out dist
221
+
222
+ - name: Upload sdist artifact
223
+ uses: actions/upload-artifact@v4
224
+ with:
225
+ name: sdist
226
+ path: dist/*.tar.gz
227
+ if-no-files-found: error
228
+ retention-days: 7
229
+
230
+ publish:
231
+ name: Publish to PyPI
232
+ needs: [build-wheels, build-sdist]
233
+ runs-on: ubuntu-latest
234
+ permissions:
235
+ contents: read
236
+ steps:
237
+ - name: Download all artifacts
238
+ uses: actions/download-artifact@v4
239
+ with:
240
+ pattern: wheel-*
241
+ merge-multiple: true
242
+ path: artifacts/wheels
243
+
244
+ - name: Download sdist
245
+ uses: actions/download-artifact@v4
246
+ with:
247
+ pattern: sdist
248
+ merge-multiple: true
249
+ path: artifacts/sdist
250
+
251
+ - name: Combine artifacts
252
+ shell: bash
253
+ run: |
254
+ set -e
255
+
256
+ # Debug: Show what we downloaded
257
+ echo "=== Artifacts structure ==="
258
+ find artifacts -type f -o -type d 2>/dev/null | sort || true
259
+ echo ""
260
+
261
+ # Create clean dist directory
262
+ mkdir -p dist
263
+
264
+ # Copy wheels from artifacts directory (handle all possible structures)
265
+ echo "=== Copying wheels ==="
266
+ find artifacts -name "*.whl" -type f -exec cp -v {} dist/ \; || true
267
+
268
+ # Copy sdist from artifacts directory (handle all possible structures)
269
+ echo "=== Copying sdist ==="
270
+ find artifacts -name "*.tar.gz" -type f -exec cp -v {} dist/ \; || true
271
+
272
+ # Verify we have files
273
+ echo ""
274
+ echo "=== Final dist contents ==="
275
+ ls -lah dist/ || echo "dist/ is empty or doesn't exist"
276
+ echo ""
277
+ echo "=== Distribution files ==="
278
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) 2>/dev/null | sort || echo "No files found"
279
+ echo ""
280
+
281
+ # Count files
282
+ WHEEL_COUNT=$(find dist -name "*.whl" -type f 2>/dev/null | wc -l || echo "0")
283
+ SDIST_COUNT=$(find dist -name "*.tar.gz" -type f 2>/dev/null | wc -l || echo "0")
284
+ echo "Wheels: $WHEEL_COUNT"
285
+ echo "Source distributions: $SDIST_COUNT"
286
+
287
+ if [ "$WHEEL_COUNT" -eq 0 ] && [ "$SDIST_COUNT" -eq 0 ]; then
288
+ echo "ERROR: No distribution files found in dist/!"
289
+ echo "Checking artifacts directory:"
290
+ find artifacts -type f 2>/dev/null || true
291
+ exit 1
292
+ fi
293
+
294
+ echo "✅ Successfully prepared $((WHEEL_COUNT + SDIST_COUNT)) distribution files"
295
+
296
+ - name: Publish to PyPI
297
+ env:
298
+ TWINE_USERNAME: __token__
299
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
300
+ run: |
301
+ set -e
302
+ pip install twine
303
+
304
+ # Check if we have files to upload
305
+ echo "=== Files to upload ==="
306
+ ls -lah dist/
307
+ echo ""
308
+
309
+ # Verify token is set (without exposing it)
310
+ if [ -z "$TWINE_PASSWORD" ]; then
311
+ echo "ERROR: PYPI_API_TOKEN secret is not set!"
312
+ exit 1
313
+ fi
314
+
315
+ echo "✅ PyPI token is configured"
316
+ echo ""
317
+
318
+ # Upload with verbose output for debugging
319
+ echo "=== Uploading to PyPI ==="
320
+ twine upload dist/* --verbose || {
321
+ echo ""
322
+ echo "❌ Upload failed. Common issues:"
323
+ echo " 1. Package version already exists on PyPI"
324
+ echo " 2. Invalid or expired PyPI API token"
325
+ echo " 3. Network/authentication error"
326
+ echo ""
327
+ echo "Check PyPI: https://pypi.org/project/rapsqlite/"
328
+ exit 1
329
+ }
330
+
331
+ echo ""
332
+ echo "✅ Successfully published to PyPI!"
333
+