palabra-ai 0.1.2__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.
- palabra_ai-0.1.2/.github/dependabot.yml +11 -0
- palabra_ai-0.1.2/.github/workflows/release.yml +183 -0
- palabra_ai-0.1.2/.github/workflows/sync-tag-to-version.yml +108 -0
- palabra_ai-0.1.2/.github/workflows/test.yml +47 -0
- palabra_ai-0.1.2/.github/workflows/version-bump.yml +128 -0
- palabra_ai-0.1.2/.gitignore +156 -0
- palabra_ai-0.1.2/.pre-commit-config.yaml +16 -0
- palabra_ai-0.1.2/CONTRIBUTING.md +229 -0
- palabra_ai-0.1.2/LICENSE +21 -0
- palabra_ai-0.1.2/MANIFEST.in +10 -0
- palabra_ai-0.1.2/Makefile +11 -0
- palabra_ai-0.1.2/PKG-INFO +390 -0
- palabra_ai-0.1.2/README.md +352 -0
- palabra_ai-0.1.2/RELEASE.md +92 -0
- palabra_ai-0.1.2/__init__.py +0 -0
- palabra_ai-0.1.2/docs/installation.md +148 -0
- palabra_ai-0.1.2/examples/audio_file.py +9 -0
- palabra_ai-0.1.2/examples/buffer.py +19 -0
- palabra_ai-0.1.2/examples/ffmpeg.py +43 -0
- palabra_ai-0.1.2/examples/microphone.py +9 -0
- palabra_ai-0.1.2/examples/speech/ar.mp3 +0 -0
- palabra_ai-0.1.2/examples/speech/en.mp3 +0 -0
- palabra_ai-0.1.2/examples/speech/es.mp3 +0 -0
- palabra_ai-0.1.2/examples/transcriptions.py +34 -0
- palabra_ai-0.1.2/palabra_ai/__init__.py +134 -0
- palabra_ai-0.1.2/palabra_ai/adapter/__init__.py +3 -0
- palabra_ai-0.1.2/palabra_ai/adapter/_common.py +23 -0
- palabra_ai-0.1.2/palabra_ai/adapter/buffer.py +165 -0
- palabra_ai-0.1.2/palabra_ai/adapter/device.py +380 -0
- palabra_ai-0.1.2/palabra_ai/adapter/file.py +162 -0
- palabra_ai-0.1.2/palabra_ai/base/__init__.py +0 -0
- palabra_ai-0.1.2/palabra_ai/base/adapter.py +50 -0
- palabra_ai-0.1.2/palabra_ai/base/enum.py +40 -0
- palabra_ai-0.1.2/palabra_ai/base/message.py +363 -0
- palabra_ai-0.1.2/palabra_ai/base/task.py +82 -0
- palabra_ai-0.1.2/palabra_ai/client.py +179 -0
- palabra_ai-0.1.2/palabra_ai/config.py +408 -0
- palabra_ai-0.1.2/palabra_ai/exc.py +6 -0
- palabra_ai-0.1.2/palabra_ai/internal/__init__.py +0 -0
- palabra_ai-0.1.2/palabra_ai/internal/audio.py +170 -0
- palabra_ai-0.1.2/palabra_ai/internal/buffer.py +135 -0
- palabra_ai-0.1.2/palabra_ai/internal/device.py +289 -0
- palabra_ai-0.1.2/palabra_ai/internal/realtime.py +195 -0
- palabra_ai-0.1.2/palabra_ai/internal/rest.py +69 -0
- palabra_ai-0.1.2/palabra_ai/internal/webrtc.py +374 -0
- palabra_ai-0.1.2/palabra_ai/internal/ws.py +180 -0
- palabra_ai-0.1.2/palabra_ai/lang.py +143 -0
- palabra_ai-0.1.2/palabra_ai/py.typed +0 -0
- palabra_ai-0.1.2/palabra_ai/task/__init__.py +1 -0
- palabra_ai-0.1.2/palabra_ai/task/buffer.py +38 -0
- palabra_ai-0.1.2/palabra_ai/task/logger.py +110 -0
- palabra_ai-0.1.2/palabra_ai/task/manager.py +238 -0
- palabra_ai-0.1.2/palabra_ai/task/realtime.py +106 -0
- palabra_ai-0.1.2/palabra_ai/task/receiver.py +146 -0
- palabra_ai-0.1.2/palabra_ai/task/sender.py +102 -0
- palabra_ai-0.1.2/palabra_ai/task/transcription.py +107 -0
- palabra_ai-0.1.2/palabra_ai/types.py +23 -0
- palabra_ai-0.1.2/palabra_ai/util/__init__.py +0 -0
- palabra_ai-0.1.2/palabra_ai/util/emoji.py +4 -0
- palabra_ai-0.1.2/palabra_ai/util/fanout_queue.py +62 -0
- palabra_ai-0.1.2/palabra_ai/util/frame_counter.py +67 -0
- palabra_ai-0.1.2/palabra_ai/util/logger.py +33 -0
- palabra_ai-0.1.2/palabra_ai/util/orjson.py +39 -0
- palabra_ai-0.1.2/palabra_ai/util/secret_strip.py +40 -0
- palabra_ai-0.1.2/palabra_ai/util/wrapper.py +34 -0
- palabra_ai-0.1.2/pyproject.toml +115 -0
- palabra_ai-0.1.2/tests/__init__.py +1 -0
- palabra_ai-0.1.2/tests/base/__init__.py +1 -0
- palabra_ai-0.1.2/tests/base/test_task.py +79 -0
- palabra_ai-0.1.2/tests/conftest.py +149 -0
- palabra_ai-0.1.2/tests/internal/conftest.py +36 -0
- palabra_ai-0.1.2/tests/internal/test_audio.py +212 -0
- palabra_ai-0.1.2/tests/internal/test_buffer.py +149 -0
- palabra_ai-0.1.2/tests/internal/test_device.py +375 -0
- palabra_ai-0.1.2/tests/internal/test_rest.py +56 -0
- palabra_ai-0.1.2/tests/internal/test_webrtc.py +313 -0
- palabra_ai-0.1.2/tests/task/__init__.py +1 -0
- palabra_ai-0.1.2/tests/test_basic.py +19 -0
- palabra_ai-0.1.2/tests/test_event.py +97 -0
- palabra_ai-0.1.2/tests/test_lang.py +70 -0
- palabra_ai-0.1.2/tests/util/__init__.py +1 -0
- palabra_ai-0.1.2/tests/util/test_fanout_queue.py +83 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
name: Create Release with Assets
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
packages: write
|
|
14
|
+
id-token: write # MANDATORY for OIDC PyPI publishing
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
with:
|
|
19
|
+
ref: ${{ github.ref }} # Use the tag ref to get the updated commit
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
run: uv python install 3.11
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: |
|
|
29
|
+
# uv builds packages using hatchling
|
|
30
|
+
uv build
|
|
31
|
+
|
|
32
|
+
- name: Check package
|
|
33
|
+
run: |
|
|
34
|
+
# Install twine as a tool (not in system Python)
|
|
35
|
+
uv tool install twine
|
|
36
|
+
uv tool run twine check dist/*
|
|
37
|
+
ls -la dist/
|
|
38
|
+
|
|
39
|
+
- name: Get version from tag
|
|
40
|
+
id: get_version
|
|
41
|
+
run: |
|
|
42
|
+
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
43
|
+
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
|
|
44
|
+
echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
45
|
+
|
|
46
|
+
# Publish to PyPI FIRST (before GitHub Release and Docker)
|
|
47
|
+
- name: Publish to PyPI
|
|
48
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
49
|
+
# No 'with' parameters needed - OIDC authentication is automatic
|
|
50
|
+
# The action will:
|
|
51
|
+
# 1. Request OIDC token from GitHub
|
|
52
|
+
# 2. Exchange it with PyPI for temporary API token
|
|
53
|
+
# 3. Upload the package using that token
|
|
54
|
+
# Your pending publisher configuration will be converted to active publisher on first use
|
|
55
|
+
|
|
56
|
+
- name: Create Release
|
|
57
|
+
uses: softprops/action-gh-release@v1
|
|
58
|
+
with:
|
|
59
|
+
tag_name: ${{ steps.get_version.outputs.TAG_NAME }}
|
|
60
|
+
name: Release ${{ steps.get_version.outputs.TAG_NAME }}
|
|
61
|
+
draft: false
|
|
62
|
+
prerelease: ${{ contains(steps.get_version.outputs.VERSION, 'a') || contains(steps.get_version.outputs.VERSION, 'b') || contains(steps.get_version.outputs.VERSION, 'rc') || contains(steps.get_version.outputs.VERSION, 'dev') }}
|
|
63
|
+
generate_release_notes: true
|
|
64
|
+
files: |
|
|
65
|
+
dist/*.whl
|
|
66
|
+
dist/*.tar.gz
|
|
67
|
+
env:
|
|
68
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
69
|
+
|
|
70
|
+
# Docker image for package distribution
|
|
71
|
+
- name: Log in to GitHub Container Registry
|
|
72
|
+
uses: docker/login-action@v3
|
|
73
|
+
with:
|
|
74
|
+
registry: ghcr.io
|
|
75
|
+
username: ${{ github.actor }}
|
|
76
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
+
|
|
78
|
+
# Try to link the package to this repository if it exists
|
|
79
|
+
- name: Link Docker package to repository
|
|
80
|
+
continue-on-error: true
|
|
81
|
+
run: |
|
|
82
|
+
OWNER_LOWER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
|
|
83
|
+
REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
|
|
84
|
+
IMAGE_BASE_NAME=$(echo "$REPO_NAME" | sed 's/^draft-//')
|
|
85
|
+
|
|
86
|
+
# Try to link the package to this repository
|
|
87
|
+
echo "Attempting to link ghcr.io/${OWNER_LOWER}/${IMAGE_BASE_NAME} to ${{ github.repository }}..."
|
|
88
|
+
|
|
89
|
+
# Get repository ID
|
|
90
|
+
REPO_ID=$(curl -s \
|
|
91
|
+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
|
92
|
+
-H "Accept: application/vnd.github.v3+json" \
|
|
93
|
+
"https://api.github.com/repos/${{ github.repository }}" | jq -r '.id')
|
|
94
|
+
|
|
95
|
+
if [ "$REPO_ID" != "null" ] && [ -n "$REPO_ID" ]; then
|
|
96
|
+
# Try to link the package to this repository
|
|
97
|
+
curl -X PUT \
|
|
98
|
+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
|
99
|
+
-H "Accept: application/vnd.github.v3+json" \
|
|
100
|
+
"https://api.github.com/orgs/${{ github.repository_owner }}/packages/container/${IMAGE_BASE_NAME}" \
|
|
101
|
+
-d "{\"repository_id\": ${REPO_ID}}" || true
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
- name: Create Dockerfile for package
|
|
105
|
+
run: |
|
|
106
|
+
cat > Dockerfile << EOF
|
|
107
|
+
FROM python:3.11-slim
|
|
108
|
+
LABEL org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
|
109
|
+
LABEL org.opencontainers.image.description="Palabra AI Python SDK"
|
|
110
|
+
LABEL org.opencontainers.image.licenses=MIT
|
|
111
|
+
LABEL org.opencontainers.image.url=https://github.com/${{ github.repository }}
|
|
112
|
+
LABEL org.opencontainers.image.documentation=https://github.com/${{ github.repository }}/blob/main/README.md
|
|
113
|
+
LABEL org.opencontainers.image.vendor="${{ github.repository_owner }}"
|
|
114
|
+
LABEL org.opencontainers.image.version="${{ steps.get_version.outputs.VERSION }}"
|
|
115
|
+
|
|
116
|
+
COPY dist/*.whl /tmp/
|
|
117
|
+
RUN pip install /tmp/*.whl && rm /tmp/*.whl
|
|
118
|
+
|
|
119
|
+
# This is a library image, not meant to be run directly
|
|
120
|
+
CMD ["python", "-c", "import palabra_ai; print(f'Palabra AI SDK v{palabra_ai.__version__} installed')"]
|
|
121
|
+
EOF
|
|
122
|
+
|
|
123
|
+
- name: Build and push Docker image with package
|
|
124
|
+
run: |
|
|
125
|
+
PACKAGE_VERSION=${{ steps.get_version.outputs.VERSION }}
|
|
126
|
+
# Convert repository owner to lowercase for Docker
|
|
127
|
+
OWNER_LOWER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
|
|
128
|
+
# Extract repository name from full repository path
|
|
129
|
+
REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
|
|
130
|
+
# Remove 'draft-' prefix if present for cleaner image name
|
|
131
|
+
IMAGE_BASE_NAME=$(echo "$REPO_NAME" | sed 's/^draft-//')
|
|
132
|
+
IMAGE_NAME=ghcr.io/${OWNER_LOWER}/${IMAGE_BASE_NAME}
|
|
133
|
+
|
|
134
|
+
docker build -t $IMAGE_NAME:$PACKAGE_VERSION -t $IMAGE_NAME:latest .
|
|
135
|
+
|
|
136
|
+
# Try to push, but don't fail the whole workflow if it doesn't work
|
|
137
|
+
if docker push $IMAGE_NAME:$PACKAGE_VERSION && docker push $IMAGE_NAME:latest; then
|
|
138
|
+
echo "📦 Successfully pushed Docker images:"
|
|
139
|
+
echo " - $IMAGE_NAME:$PACKAGE_VERSION"
|
|
140
|
+
echo " - $IMAGE_NAME:latest"
|
|
141
|
+
|
|
142
|
+
# Save image name for use in summary
|
|
143
|
+
echo "IMAGE_NAME=$IMAGE_NAME" >> $GITHUB_ENV
|
|
144
|
+
echo "IMAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV
|
|
145
|
+
echo "DOCKER_PUSH_SUCCESS=true" >> $GITHUB_ENV
|
|
146
|
+
else
|
|
147
|
+
echo "⚠️ Failed to push Docker images to $IMAGE_NAME"
|
|
148
|
+
echo "This might be due to permissions or existing package conflicts"
|
|
149
|
+
echo "PyPI publishing will continue..."
|
|
150
|
+
echo "DOCKER_PUSH_SUCCESS=false" >> $GITHUB_ENV
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
- name: Release Summary
|
|
154
|
+
run: |
|
|
155
|
+
echo "## 🎉 Release Summary" >> $GITHUB_STEP_SUMMARY
|
|
156
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
157
|
+
echo "### 📦 Package Information" >> $GITHUB_STEP_SUMMARY
|
|
158
|
+
echo "- **Repository**: ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
|
|
159
|
+
echo "- **Tag**: ${{ steps.get_version.outputs.TAG_NAME }}" >> $GITHUB_STEP_SUMMARY
|
|
160
|
+
echo "- **Version**: ${{ steps.get_version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
|
|
161
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
162
|
+
echo "### 🚀 Published Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
163
|
+
echo "- **GitHub Release**: https://github.com/${{ github.repository }}/releases/tag/${{ steps.get_version.outputs.TAG_NAME }}" >> $GITHUB_STEP_SUMMARY
|
|
164
|
+
if [ "${{ env.DOCKER_PUSH_SUCCESS }}" == "true" ]; then
|
|
165
|
+
echo "- **Docker Image**: \`${{ env.IMAGE_NAME }}:${{ env.IMAGE_VERSION }}\`" >> $GITHUB_STEP_SUMMARY
|
|
166
|
+
else
|
|
167
|
+
echo "- **Docker Image**: ⚠️ Failed to publish (permissions issue)" >> $GITHUB_STEP_SUMMARY
|
|
168
|
+
fi
|
|
169
|
+
echo "- **PyPI Package**: https://pypi.org/project/palabra-ai/" >> $GITHUB_STEP_SUMMARY
|
|
170
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
171
|
+
echo "### 📥 Installation" >> $GITHUB_STEP_SUMMARY
|
|
172
|
+
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
|
|
173
|
+
echo "# PyPI" >> $GITHUB_STEP_SUMMARY
|
|
174
|
+
echo "pip install palabra-ai==${{ steps.get_version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
|
|
175
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
176
|
+
if [ "${{ env.DOCKER_PUSH_SUCCESS }}" == "true" ]; then
|
|
177
|
+
echo "# Docker" >> $GITHUB_STEP_SUMMARY
|
|
178
|
+
echo "docker pull ${{ env.IMAGE_NAME }}:${{ env.IMAGE_VERSION }}" >> $GITHUB_STEP_SUMMARY
|
|
179
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
180
|
+
fi
|
|
181
|
+
echo "# From release assets" >> $GITHUB_STEP_SUMMARY
|
|
182
|
+
echo "pip install https://github.com/${{ github.repository }}/releases/download/${{ steps.get_version.outputs.TAG_NAME }}/palabra_ai-${{ steps.get_version.outputs.VERSION }}-py3-none-any.whl" >> $GITHUB_STEP_SUMMARY
|
|
183
|
+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
name: Update Version from Tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
update-version:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
+
fetch-depth: 0 # Need full history to update tag
|
|
19
|
+
|
|
20
|
+
- name: Extract version from tag
|
|
21
|
+
id: extract_version
|
|
22
|
+
run: |
|
|
23
|
+
# Get tag name and remove 'v' prefix
|
|
24
|
+
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
|
25
|
+
VERSION="${TAG_NAME#v}"
|
|
26
|
+
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
|
|
27
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
28
|
+
echo "Tag: $TAG_NAME, Version: $VERSION"
|
|
29
|
+
|
|
30
|
+
- name: Update version in pyproject.toml and __init__.py
|
|
31
|
+
run: |
|
|
32
|
+
VERSION="${{ steps.extract_version.outputs.version }}"
|
|
33
|
+
|
|
34
|
+
# Update pyproject.toml and __init__.py using Python for safety
|
|
35
|
+
python << 'EOF'
|
|
36
|
+
import re
|
|
37
|
+
import os
|
|
38
|
+
|
|
39
|
+
version = os.environ.get('VERSION', '${{ steps.extract_version.outputs.version }}')
|
|
40
|
+
|
|
41
|
+
# Update pyproject.toml
|
|
42
|
+
with open('pyproject.toml', 'r') as f:
|
|
43
|
+
content = f.read()
|
|
44
|
+
|
|
45
|
+
# Replace version - handle any spacing and quote style
|
|
46
|
+
pattern = r'(version\s*=\s*["\'])([0-9]+\.[0-9]+\.[0-9]+(?:(?:a|b|rc|dev)[0-9]+)?)(["\'])'
|
|
47
|
+
replacement = rf'\g<1>{version}\g<3>'
|
|
48
|
+
content = re.sub(pattern, replacement, content)
|
|
49
|
+
|
|
50
|
+
with open('pyproject.toml', 'w') as f:
|
|
51
|
+
f.write(content)
|
|
52
|
+
|
|
53
|
+
# Update src/palabra_ai/__init__.py
|
|
54
|
+
with open('src/palabra_ai/__init__.py', 'r') as f:
|
|
55
|
+
content = f.read()
|
|
56
|
+
|
|
57
|
+
# Replace __version__ - handle any spacing and quote style
|
|
58
|
+
pattern = r'(__version__\s*=\s*["\'])([0-9]+\.[0-9]+\.[0-9]+(?:(?:a|b|rc|dev)[0-9]+)?)(["\'])'
|
|
59
|
+
replacement = rf'\g<1>{version}\g<3>'
|
|
60
|
+
content = re.sub(pattern, replacement, content)
|
|
61
|
+
|
|
62
|
+
with open('src/palabra_ai/__init__.py', 'w') as f:
|
|
63
|
+
f.write(content)
|
|
64
|
+
EOF
|
|
65
|
+
|
|
66
|
+
# Configure git
|
|
67
|
+
git config --local user.email "action@github.com"
|
|
68
|
+
git config --local user.name "GitHub Action"
|
|
69
|
+
|
|
70
|
+
# Check if there are changes
|
|
71
|
+
if git diff --quiet; then
|
|
72
|
+
echo "No changes needed - version already matches tag"
|
|
73
|
+
echo "skip_update=true" >> $GITHUB_ENV
|
|
74
|
+
else
|
|
75
|
+
# Commit changes
|
|
76
|
+
git add pyproject.toml src/palabra_ai/__init__.py
|
|
77
|
+
git commit -m "Update version to $VERSION from tag ${{ steps.extract_version.outputs.tag_name }}"
|
|
78
|
+
echo "skip_update=false" >> $GITHUB_ENV
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
- name: Update tag to point to new commit
|
|
82
|
+
if: env.skip_update == 'false'
|
|
83
|
+
run: |
|
|
84
|
+
TAG_NAME="${{ steps.extract_version.outputs.tag_name }}"
|
|
85
|
+
|
|
86
|
+
# Push the commit to main
|
|
87
|
+
git push origin HEAD:main
|
|
88
|
+
|
|
89
|
+
# Force update the tag to point to the new commit
|
|
90
|
+
git tag -f $TAG_NAME
|
|
91
|
+
git push origin $TAG_NAME --force
|
|
92
|
+
|
|
93
|
+
echo "✅ Tag $TAG_NAME now points to the commit with updated version"
|
|
94
|
+
|
|
95
|
+
- name: Summary
|
|
96
|
+
run: |
|
|
97
|
+
if [ "${{ env.skip_update }}" == "true" ]; then
|
|
98
|
+
echo "## No Update Needed 🟢" >> $GITHUB_STEP_SUMMARY
|
|
99
|
+
echo "Version in pyproject.toml and __init__.py already matches tag ${{ steps.extract_version.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
|
|
100
|
+
else
|
|
101
|
+
echo "## Version Updated! 🎉" >> $GITHUB_STEP_SUMMARY
|
|
102
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
103
|
+
echo "- **Tag**: ${{ steps.extract_version.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
|
|
104
|
+
echo "- **Version**: ${{ steps.extract_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
105
|
+
echo "- **Action**: Updated pyproject.toml and __init__.py, moved tag to new commit" >> $GITHUB_STEP_SUMMARY
|
|
106
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
107
|
+
echo "The release workflow will start automatically for the updated tag." >> $GITHUB_STEP_SUMMARY
|
|
108
|
+
fi
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install system dependencies
|
|
26
|
+
run: |
|
|
27
|
+
sudo apt-get update
|
|
28
|
+
sudo apt-get install -y portaudio19-dev
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@v4
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: |
|
|
35
|
+
uv sync --all-extras --dev
|
|
36
|
+
|
|
37
|
+
- name: Run tests with pytest
|
|
38
|
+
run: |
|
|
39
|
+
uv run pytest -vs --cov=palabra_ai --cov-report=xml --cov-report=html
|
|
40
|
+
|
|
41
|
+
- name: Upload coverage to Codecov
|
|
42
|
+
uses: codecov/codecov-action@v4
|
|
43
|
+
with:
|
|
44
|
+
file: ./coverage.xml
|
|
45
|
+
flags: unittests
|
|
46
|
+
name: codecov-umbrella
|
|
47
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
name: Version Bump
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
bump_type:
|
|
7
|
+
description: 'Version bump type'
|
|
8
|
+
required: true
|
|
9
|
+
default: 'patch'
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- patch
|
|
13
|
+
- minor
|
|
14
|
+
- major
|
|
15
|
+
- alpha
|
|
16
|
+
- beta
|
|
17
|
+
- rc
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
create-version-tag:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: write
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
with:
|
|
28
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: '3.11'
|
|
34
|
+
|
|
35
|
+
- name: Get current version
|
|
36
|
+
id: current_version
|
|
37
|
+
run: |
|
|
38
|
+
python << 'EOF'
|
|
39
|
+
import re
|
|
40
|
+
import sys
|
|
41
|
+
|
|
42
|
+
with open('pyproject.toml', 'r') as f:
|
|
43
|
+
content = f.read()
|
|
44
|
+
match = re.search(r'version\s*=\s*["\']([0-9]+\.[0-9]+\.[0-9]+(?:(?:a|b|rc|dev)[0-9]+)?)["\']', content)
|
|
45
|
+
if match:
|
|
46
|
+
print(f"version={match.group(1)}")
|
|
47
|
+
else:
|
|
48
|
+
print('ERROR: Version not found', file=sys.stderr)
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
EOF >> $GITHUB_OUTPUT
|
|
51
|
+
|
|
52
|
+
- name: Calculate new version
|
|
53
|
+
id: new_version
|
|
54
|
+
run: |
|
|
55
|
+
python << 'EOF'
|
|
56
|
+
import re
|
|
57
|
+
import os
|
|
58
|
+
import sys
|
|
59
|
+
|
|
60
|
+
current = "${{ steps.current_version.outputs.version }}"
|
|
61
|
+
bump_type = "${{ github.event.inputs.bump_type }}"
|
|
62
|
+
|
|
63
|
+
# Parse current version
|
|
64
|
+
match = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)(?:(a|b|rc)([0-9]+))?', current)
|
|
65
|
+
if not match:
|
|
66
|
+
print(f"ERROR: Invalid version format: {current}", file=sys.stderr)
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
69
|
+
major = int(match.group(1))
|
|
70
|
+
minor = int(match.group(2))
|
|
71
|
+
patch = int(match.group(3))
|
|
72
|
+
pre_type = match.group(4)
|
|
73
|
+
pre_num = int(match.group(5)) if match.group(5) else 0
|
|
74
|
+
|
|
75
|
+
# Calculate new version
|
|
76
|
+
if bump_type == "major":
|
|
77
|
+
major += 1
|
|
78
|
+
minor = 0
|
|
79
|
+
patch = 0
|
|
80
|
+
new_version = f"{major}.{minor}.{patch}"
|
|
81
|
+
elif bump_type == "minor":
|
|
82
|
+
minor += 1
|
|
83
|
+
patch = 0
|
|
84
|
+
new_version = f"{major}.{minor}.{patch}"
|
|
85
|
+
elif bump_type == "patch":
|
|
86
|
+
if pre_type: # If current is pre-release, just remove pre-release
|
|
87
|
+
new_version = f"{major}.{minor}.{patch}"
|
|
88
|
+
else:
|
|
89
|
+
patch += 1
|
|
90
|
+
new_version = f"{major}.{minor}.{patch}"
|
|
91
|
+
elif bump_type in ["alpha", "beta", "rc"]:
|
|
92
|
+
if pre_type == bump_type[0]: # Same pre-release type
|
|
93
|
+
pre_num += 1
|
|
94
|
+
else:
|
|
95
|
+
pre_num = 1
|
|
96
|
+
new_version = f"{major}.{minor}.{patch}{bump_type[0]}{pre_num}"
|
|
97
|
+
|
|
98
|
+
# Write to GitHub output
|
|
99
|
+
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
|
|
100
|
+
f.write(f"version={new_version}\n")
|
|
101
|
+
|
|
102
|
+
print(f"New version: {new_version}")
|
|
103
|
+
EOF
|
|
104
|
+
|
|
105
|
+
- name: Create and push tag
|
|
106
|
+
run: |
|
|
107
|
+
git config --local user.email "action@github.com"
|
|
108
|
+
git config --local user.name "GitHub Action"
|
|
109
|
+
|
|
110
|
+
# Create tag
|
|
111
|
+
git tag v${{ steps.new_version.outputs.version }}
|
|
112
|
+
|
|
113
|
+
# Push tag - this will trigger sync-tag-to-version workflow
|
|
114
|
+
git push origin v${{ steps.new_version.outputs.version }}
|
|
115
|
+
|
|
116
|
+
- name: Summary
|
|
117
|
+
run: |
|
|
118
|
+
echo "## Version Tag Created! 🎉" >> $GITHUB_STEP_SUMMARY
|
|
119
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
120
|
+
echo "- **From**: ${{ steps.current_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
121
|
+
echo "- **To**: ${{ steps.new_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
122
|
+
echo "- **Type**: ${{ github.event.inputs.bump_type }}" >> $GITHUB_STEP_SUMMARY
|
|
123
|
+
echo "- **Tag**: v${{ steps.new_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
124
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
125
|
+
echo "The tag will trigger:" >> $GITHUB_STEP_SUMMARY
|
|
126
|
+
echo "1. Update version in pyproject.toml to match the tag" >> $GITHUB_STEP_SUMMARY
|
|
127
|
+
echo "2. Move the tag to the commit with updated version" >> $GITHUB_STEP_SUMMARY
|
|
128
|
+
echo "3. Create a release automatically" >> $GITHUB_STEP_SUMMARY
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.nox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
.cache
|
|
44
|
+
nosetests.xml
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
*.py,cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
.pytest_cache/
|
|
50
|
+
cover/
|
|
51
|
+
|
|
52
|
+
# Translations
|
|
53
|
+
*.mo
|
|
54
|
+
*.pot
|
|
55
|
+
|
|
56
|
+
# Django stuff:
|
|
57
|
+
*.log
|
|
58
|
+
local_settings.py
|
|
59
|
+
db.sqlite3
|
|
60
|
+
db.sqlite3-journal
|
|
61
|
+
|
|
62
|
+
# Flask stuff:
|
|
63
|
+
instance/
|
|
64
|
+
.webassets-cache
|
|
65
|
+
|
|
66
|
+
# Scrapy stuff:
|
|
67
|
+
.scrapy
|
|
68
|
+
|
|
69
|
+
# Sphinx documentation
|
|
70
|
+
docs/_build/
|
|
71
|
+
|
|
72
|
+
# PyBuilder
|
|
73
|
+
.pybuilder/
|
|
74
|
+
target/
|
|
75
|
+
|
|
76
|
+
# Jupyter Notebook
|
|
77
|
+
.ipynb_checkpoints
|
|
78
|
+
|
|
79
|
+
# IPython
|
|
80
|
+
profile_default/
|
|
81
|
+
ipython_config.py
|
|
82
|
+
|
|
83
|
+
# pyenv
|
|
84
|
+
.python-version
|
|
85
|
+
|
|
86
|
+
# pipenv
|
|
87
|
+
Pipfile.lock
|
|
88
|
+
|
|
89
|
+
# poetry
|
|
90
|
+
poetry.lock
|
|
91
|
+
|
|
92
|
+
# pdm
|
|
93
|
+
.pdm.toml
|
|
94
|
+
.pdm-python
|
|
95
|
+
.pdm-build/
|
|
96
|
+
|
|
97
|
+
# PEP 582
|
|
98
|
+
__pypackages__/
|
|
99
|
+
|
|
100
|
+
# Celery stuff
|
|
101
|
+
celerybeat-schedule
|
|
102
|
+
celerybeat.pid
|
|
103
|
+
|
|
104
|
+
# SageMath parsed files
|
|
105
|
+
*.sage.py
|
|
106
|
+
|
|
107
|
+
# Environments
|
|
108
|
+
.env
|
|
109
|
+
.venv
|
|
110
|
+
env/
|
|
111
|
+
venv/
|
|
112
|
+
ENV/
|
|
113
|
+
env.bak/
|
|
114
|
+
venv.bak/
|
|
115
|
+
|
|
116
|
+
# Spyder project settings
|
|
117
|
+
.spyderproject
|
|
118
|
+
.spyproject
|
|
119
|
+
|
|
120
|
+
# Rope project settings
|
|
121
|
+
.ropeproject
|
|
122
|
+
|
|
123
|
+
# mkdocs documentation
|
|
124
|
+
/site
|
|
125
|
+
|
|
126
|
+
# mypy
|
|
127
|
+
.mypy_cache/
|
|
128
|
+
.dmypy.json
|
|
129
|
+
dmypy.json
|
|
130
|
+
|
|
131
|
+
# Pyre type checker
|
|
132
|
+
.pyre/
|
|
133
|
+
|
|
134
|
+
# pytype static type analyzer
|
|
135
|
+
.pytype/
|
|
136
|
+
|
|
137
|
+
# Cython debug symbols
|
|
138
|
+
cython_debug/
|
|
139
|
+
|
|
140
|
+
# PyCharm
|
|
141
|
+
.idea/
|
|
142
|
+
|
|
143
|
+
# VSCode
|
|
144
|
+
.vscode/
|
|
145
|
+
|
|
146
|
+
# macOS
|
|
147
|
+
.DS_Store
|
|
148
|
+
|
|
149
|
+
# Windows
|
|
150
|
+
Thumbs.db
|
|
151
|
+
ehthumbs.db
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# uv
|
|
156
|
+
uv.lock
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.5.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
- id: check-merge-conflict
|
|
10
|
+
|
|
11
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
|
+
rev: v0.7.0
|
|
13
|
+
hooks:
|
|
14
|
+
- id: ruff
|
|
15
|
+
args: [--fix]
|
|
16
|
+
- id: ruff-format
|