|
| 1 | +# GitHub Workflows |
| 2 | + |
| 3 | +This directory contains GitHub Actions workflows for the SinricPro Python SDK. |
| 4 | + |
| 5 | +## Workflows |
| 6 | + |
| 7 | +### 1. PR Validation (`pr-validation.yml`) |
| 8 | + |
| 9 | +**Trigger:** Automatically runs on pull requests to main branches |
| 10 | + |
| 11 | +**Purpose:** Validates code quality and ensures all examples compile correctly |
| 12 | + |
| 13 | +**Jobs:** |
| 14 | +- **validate-examples**: Tests all example files across Python 3.10, 3.11, and 3.12 |
| 15 | + - Uses `.github/scripts/validate_examples.py` to validate syntax and imports |
| 16 | + - Validates Python syntax using AST parsing |
| 17 | + - Tests that all sinricpro imports work correctly |
| 18 | + |
| 19 | +- **lint-check**: Runs code quality checks |
| 20 | + - Ruff for code linting |
| 21 | + - MyPy for type checking |
| 22 | + |
| 23 | +- **package-build**: Tests package building |
| 24 | + - Builds wheel and source distribution |
| 25 | + - Validates with `twine check` |
| 26 | + |
| 27 | +**What it validates:** |
| 28 | +- ✅ All example files have valid Python syntax |
| 29 | +- ✅ All imports in examples are correct |
| 30 | +- ✅ Package can be built successfully |
| 31 | +- ✅ Code passes linting checks (non-blocking) |
| 32 | +- ✅ Type hints are correct (non-blocking) |
| 33 | + |
| 34 | +### 2. Publish Release (`publish-release.yml`) |
| 35 | + |
| 36 | +**Trigger:** Manual workflow dispatch |
| 37 | + |
| 38 | +**Purpose:** Publishes a new version to PyPI and creates a GitHub release |
| 39 | + |
| 40 | +**Required Secrets:** |
| 41 | +- `PYPI_API_TOKEN`: PyPI API token for publishing packages |
| 42 | + - Get from: https://pypi.org/manage/account/token/ |
| 43 | + - Add to: Repository Settings → Secrets and variables → Actions → New repository secret |
| 44 | + |
| 45 | +**Input Parameters:** |
| 46 | +- `version`: Version number (e.g., `3.0.0` or `3.0.0-beta.1`) |
| 47 | +- `branch`: Branch or tag to publish from (default: `main`) |
| 48 | +- `prerelease`: Mark as pre-release (checkbox) |
| 49 | + |
| 50 | +**Jobs:** |
| 51 | + |
| 52 | +1. **validate-version** |
| 53 | + - Validates version format (X.Y.Z or X.Y.Z-suffix) |
| 54 | + - Checks that git tag doesn't already exist |
| 55 | + |
| 56 | +2. **build-and-test** |
| 57 | + - Updates version in `sinricpro/__init__.py` |
| 58 | + - Builds package (wheel + source distribution) |
| 59 | + - Validates with `twine check` |
| 60 | + - Tests local installation |
| 61 | + - Uploads artifacts for next jobs |
| 62 | + |
| 63 | +3. **publish-to-pypi** |
| 64 | + - Downloads build artifacts |
| 65 | + - Publishes to PyPI using official PyPI publish action |
| 66 | + - Waits for propagation |
| 67 | + - Verifies package is available on PyPI |
| 68 | + |
| 69 | +4. **create-github-release** |
| 70 | + - Creates and pushes git tag (`vX.Y.Z`) |
| 71 | + - Generates changelog from git commits |
| 72 | + - Creates GitHub release with: |
| 73 | + - Release notes |
| 74 | + - Attached wheel and source files |
| 75 | + - Links to PyPI package |
| 76 | + |
| 77 | +**Workflow Summary:** |
| 78 | +After successful completion, the workflow creates a summary with: |
| 79 | +- Version number |
| 80 | +- PyPI package link |
| 81 | +- GitHub release link |
| 82 | +- Installation command |
| 83 | + |
| 84 | +## How to Use |
| 85 | + |
| 86 | +### Setting up PyPI Publishing |
| 87 | + |
| 88 | +1. **Create PyPI API Token:** |
| 89 | + ```bash |
| 90 | + # Go to https://pypi.org/manage/account/token/ |
| 91 | + # Create a new API token with scope: "Entire account" or specific to "sinricpro" |
| 92 | + # Copy the token (starts with pypi-...) |
| 93 | + ``` |
| 94 | + |
| 95 | +2. **Add Token to GitHub Secrets:** |
| 96 | + - Go to repository Settings → Secrets and variables → Actions |
| 97 | + - Click "New repository secret" |
| 98 | + - Name: `PYPI_API_TOKEN` |
| 99 | + - Value: Paste your PyPI token |
| 100 | + - Click "Add secret" |
| 101 | + |
| 102 | +### Publishing a Release |
| 103 | + |
| 104 | +1. **Go to Actions tab** in your repository |
| 105 | + |
| 106 | +2. **Select "Publish Release to PyPI"** from the workflows list |
| 107 | + |
| 108 | +3. **Click "Run workflow"** button |
| 109 | + |
| 110 | +4. **Fill in the parameters:** |
| 111 | + - **Version**: Enter version number (e.g., `3.0.1`) |
| 112 | + - **Branch**: Select branch to publish from (usually `main`) |
| 113 | + - **Prerelease**: Check if this is a pre-release version |
| 114 | + |
| 115 | +5. **Click "Run workflow"** |
| 116 | + |
| 117 | +6. **Monitor the workflow:** |
| 118 | + - Watch each job complete |
| 119 | + - Check for any errors |
| 120 | + - View the summary for installation instructions |
| 121 | + |
| 122 | +### Version Numbering Guidelines |
| 123 | + |
| 124 | +**Stable releases:** |
| 125 | +- `3.0.0` - Major version |
| 126 | +- `3.0.1` - Patch version |
| 127 | +- `3.1.0` - Minor version |
| 128 | + |
| 129 | +**Pre-releases:** |
| 130 | +- `3.0.0-alpha.1` - Alpha release |
| 131 | +- `3.0.0-beta.1` - Beta release |
| 132 | +- `3.0.0-rc.1` - Release candidate |
| 133 | + |
| 134 | +### Testing Before Release |
| 135 | + |
| 136 | +Before publishing a release: |
| 137 | + |
| 138 | +1. **Test locally:** |
| 139 | + ```bash |
| 140 | + # Build the package |
| 141 | + python -m build |
| 142 | + |
| 143 | + # Check with twine |
| 144 | + twine check dist/* |
| 145 | + |
| 146 | + # Install locally |
| 147 | + pip install dist/*.whl |
| 148 | + |
| 149 | + # Test import |
| 150 | + python -c "import sinricpro; print(sinricpro.__version__)" |
| 151 | + ``` |
| 152 | + |
| 153 | +2. **Test examples:** |
| 154 | + ```bash |
| 155 | + # Validate all examples |
| 156 | + python -m compileall examples/ |
| 157 | + ``` |
| 158 | + |
| 159 | +3. **Run tests (if available):** |
| 160 | + ```bash |
| 161 | + pytest tests/ |
| 162 | + ``` |
| 163 | + |
| 164 | +### Troubleshooting |
| 165 | + |
| 166 | +**"Tag already exists" error:** |
| 167 | +- The version tag already exists in git |
| 168 | +- Choose a different version number or delete the existing tag |
| 169 | + |
| 170 | +**"PyPI upload failed" error:** |
| 171 | +- Check that `PYPI_API_TOKEN` secret is set correctly |
| 172 | +- Verify token has correct permissions |
| 173 | +- Ensure version doesn't already exist on PyPI |
| 174 | + |
| 175 | +**"Package build failed" error:** |
| 176 | +- Check `pyproject.toml` for syntax errors |
| 177 | +- Verify all dependencies are listed correctly |
| 178 | +- Check that version number is valid |
| 179 | + |
| 180 | +**"Import error in examples" (PR validation):** |
| 181 | +- Missing import in example file |
| 182 | +- Typo in module name |
| 183 | +- New module not exported in `__init__.py` |
| 184 | + |
| 185 | +## Workflow Permissions |
| 186 | + |
| 187 | +The workflows require the following permissions: |
| 188 | + |
| 189 | +- `contents: write` - For creating tags and releases |
| 190 | +- `packages: write` - For publishing to PyPI (via PYPI_API_TOKEN) |
| 191 | + |
| 192 | +These are automatically granted in the workflow files. |
| 193 | + |
| 194 | +## Best Practices |
| 195 | + |
| 196 | +1. **Always test locally before publishing** |
| 197 | +2. **Use semantic versioning (semver.org)** |
| 198 | +3. **Write meaningful release notes** |
| 199 | +4. **Test examples after each change** |
| 200 | +5. **Keep dependencies up to date** |
| 201 | +6. **Tag releases consistently (vX.Y.Z format)** |
| 202 | + |
| 203 | +## Scripts |
| 204 | + |
| 205 | +The `.github/scripts/` directory contains helper scripts used by the workflows: |
| 206 | + |
| 207 | +### validate_examples.py |
| 208 | + |
| 209 | +Validates all Python example files in the `examples/` directory: |
| 210 | +- Checks Python syntax using AST parsing |
| 211 | +- Verifies that all `sinricpro` imports are valid |
| 212 | +- Provides detailed output for debugging |
| 213 | +- Returns exit code 0 on success, 1 on failure |
| 214 | + |
| 215 | +**Usage:** |
| 216 | +```bash |
| 217 | +python .github/scripts/validate_examples.py |
| 218 | +``` |
| 219 | + |
| 220 | +**Output:** |
| 221 | +``` |
| 222 | +Found 16 Python example files |
| 223 | +
|
| 224 | +============================================================ |
| 225 | +Validating Python syntax... |
| 226 | +============================================================ |
| 227 | + ✓ Syntax valid: examples/switch/switch_example.py |
| 228 | + ✓ Syntax valid: examples/light/light_example.py |
| 229 | + ... |
| 230 | +
|
| 231 | +============================================================ |
| 232 | +Validating sinricpro imports... |
| 233 | +============================================================ |
| 234 | +Checking: examples/switch/switch_example.py |
| 235 | + ✓ Import OK: sinricpro |
| 236 | + ... |
| 237 | +
|
| 238 | +============================================================ |
| 239 | +✅ All examples validated successfully! |
| 240 | +``` |
| 241 | + |
| 242 | +## Support |
| 243 | + |
| 244 | +If you encounter issues with the workflows: |
| 245 | +- Check the workflow run logs in GitHub Actions |
| 246 | +- Review the troubleshooting section above |
| 247 | +- Open an issue in the repository |
0 commit comments