Skip to content

Add git precommit hook and github actions #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/sh

# Get list of files that are staged for commit
KT_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '^android/.*\.kt$' || true)
GRADLE_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '.*\.gradle\.kts$' || true)
CPP_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '^(jni/.*\.(cpp|h|c|hpp|cc)|cli/.*\.(cpp|h|c|hpp|cc)|cpp/.*\.(cpp|h|c|hpp|cc))$' || true)

# Run spotless checks if needed
if [ -n "$KT_FILES" ]; then
echo "Running spotlessKotlinCheck..."
./gradlew spotlessKotlinCheck
if [ $? -ne 0 ]; then
echo "❌ Kotlin files need formatting. Please run './gradlew spotlessKotlinApply' or 'make format' and commit again."
exit 1
fi
fi

if [ -n "$GRADLE_FILES" ]; then
echo "Running spotlessKotlinGradleCheck..."
./gradlew spotlessKotlinGradleCheck
if [ $? -ne 0 ]; then
echo "❌ Gradle files need formatting. Please run './gradlew spotlessKotlinGradleApply' or 'make format' and commit again."
exit 1
fi
fi

if [ -n "$CPP_FILES" ]; then
echo "Running spotlessCppCheck..."
./gradlew spotlessCppCheck
if [ $? -ne 0 ]; then
echo "❌ C++ files need formatting. Please run './gradlew spotlessCppApply' or 'make format' and commit again."
exit 1
fi
fi
81 changes: 81 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: PR Checks

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main

jobs:
check-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: gradle

- name: Install clang-format 14 (native)
run: |
sudo apt update
sudo apt install -y clang-format-14
sudo ln -sf /usr/bin/clang-format-14 /usr/local/bin/clang-format
clang-format --version

- name: Verify clang-format installation
run: |
if ! command -v clang-format >/dev/null; then
echo "❌ clang-format not found"
exit 1
fi
clang-format --version

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Run spotlessCheck
run: |
echo "Running spotlessCheck..."
./gradlew spotlessCheck
if [ $? -ne 0 ]; then
echo "❌ spotlessCheck failed. Please run './gradlew spotlessApply' locally to fix formatting issues."
exit 1
fi

build-test-kotlin:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: gradle

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Run detekt
run: |
echo "Running detekt..."
./gradlew detekt
if [ $? -ne 0 ]; then
echo "❌ detekt found code style issues. Please fix them locally."
exit 1
fi

- name: Run unit tests
run: |
echo "Running unit tests..."
./gradlew testDebugUnitTest
if [ $? -ne 0 ]; then
echo "❌ Unit tests failed. Please fix the failing tests locally."
exit 1
fi
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,64 @@ With `all` option, it will conduct deep clean including open source components.

WhisperKit Android is currently in the beta stage. We are actively developing the project and welcome contributions from the community.

## Development Setup

### Installing clang-format

The project uses clang-format 14 for C++ code formatting. You'll need to install it based on your operating system:

#### macOS
```bash
# Install LLVM 14
brew install llvm@14

# Create symlink for clang-format
sudo ln -sf /opt/homebrew/opt/llvm@14/bin/clang-format /opt/homebrew/bin/clang-format
```

#### Linux (Ubuntu/Debian)
```bash
sudo apt update
sudo apt install -y clang-format-14
sudo ln -sf /usr/bin/clang-format-14 /usr/local/bin/clang-format
```

Verify the installation:
```bash
clang-format --version
```

To check C++ code formatting:
```bash
./gradlew spotlessCppCheck
```

## Git Hooks

This project uses Git hooks to maintain code quality. These hooks help ensure consistent code formatting and quality standards.

### Setup

To use the Git hooks, run the following command in your repository root:

```bash
git config core.hooksPath .githooks
```

### Available Hooks

#### pre-commit
- Runs `spotlessApply` to automatically fix code formatting issues
- If formatting fixes are applied, they are automatically staged
- The commit will be blocked if `spotlessApply` fails

### Troubleshooting

If you need to bypass the hooks temporarily (not recommended), you can use:
```bash
git commit --no-verify
```

# License

- We release WhisperKit Android under [MIT License](LICENSE).
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ spotless {
"cpp/**/*.cpp", "cpp/**/*.h", "cpp/**/*.c", "cpp/**/*.hpp", "cpp/**/*.cc",
)
targetExclude("**/build/**", "**/external/**")
clangFormat("20.1.5")
clangFormat("14.0.6")
}
}
8 changes: 4 additions & 4 deletions cpp/src/Models/TextDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ bool is_exact_match_for_separate_kv_cache_no_alignment_heads(const tflite::Model
}

/* helper functions to calculate the number of inputs and outputs for a given number of layers */
auto calculate_num_inputs_for_variant_with_layers = [=](const int num_layers) -> auto {
auto calculate_num_inputs_for_variant_with_layers = [=](const int num_layers) -> auto{
return num_shared_inputs + num_layers * kv_factor;
};

auto calculate_num_outputs_for_variant_with_layers = [=](const int num_layers) -> auto {
auto calculate_num_outputs_for_variant_with_layers = [=](const int num_layers) -> auto{
return kv_factor * num_layers + 1;
};

auto output_names_for_variant_with_layers = [=](const int num_layers) -> auto {
auto output_names_for_variant_with_layers = [=](const int num_layers) -> auto{
std::unordered_set<std::string> output_names;
output_names.insert(std::string("logits"));
for (int i = 0; i < num_layers; ++i) {
Expand All @@ -119,7 +119,7 @@ bool is_exact_match_for_separate_kv_cache_no_alignment_heads(const tflite::Model
return output_names;
};

auto input_names_for_variant_with_layers = [](const int num_layers) -> auto {
auto input_names_for_variant_with_layers = [](const int num_layers) -> auto{
std::unordered_set<std::string> input_names;
input_names.insert(std::string("x"));
input_names.insert(std::string("index"));
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/Text/post_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#define LOGITS_TO_NEG_INF(start, end) \
for (auto iter = (start); iter != (end); iter++) *iter = -1e9;

#define DEC_2_ROUND(x) (round((x) * 100.0) / 100.0)
#define DEC_2_ROUND(x) (round((x)*100.0) / 100.0)

using namespace std;
using json = nlohmann::json;
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/Text/post_proc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ constexpr const uint32_t SAMPLE_BEGIN = 1;
class PostProcModel : public MODEL_SUPER_CLASS {
public:
PostProcModel(Tokenizer* tokenizer, bool timestamp_text = false);
virtual ~PostProcModel() {};
virtual ~PostProcModel(){};

bool initialize(bool debug = false);
virtual void invoke(bool measure_time = false);
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/WhisperKitConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "WhisperKitPipeline.hpp"
#include "backend_class.hpp"

whisperkit_configuration_t::whisperkit_configuration_t() {};
whisperkit_configuration_t::whisperkit_configuration_t(){};

void whisperkit_configuration_t::set_audio_encoder(const char* audio_encoder) noexcept {
this->audio_encoder = audio_encoder;
Expand Down