Skip to content
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
51 changes: 51 additions & 0 deletions .github/ISSUE_TEMPLATE/BugReport.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Bug Report
description: Report a bug
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Please fill out the sections below to help everyone identify and fix the bug
- type: textarea
id: description
attributes:
label: Describe your issue
placeholder: When I click here this happens
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. Enhance this function
2. Refactor this
3. Refactor that
validations:
required: true
- type: textarea
id: expected
attributes:
label: What was the expected result?
placeholder: I expected this to happen
- type: textarea
id: screenshots
attributes:
label: Put here any screenshots or videos (optional)
- type: textarea
id: deviceinfo
attributes:
label: Your OS and Browser (optional)
placeholder: |
- OS: Windows 10
- Browser: Chrome 90.0
- type: dropdown
id: assign
attributes:
label: "Would you like to work on this issue?"
options:
- "Yes"
- type: markdown
attributes:
value: |
Thanks for reporting this issue! We will get back to you as soon as possible.
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/NewFeature.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: New feature
description: Suggest or request a new feature
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Please fill out the sections below to properly describe the new feature you are suggesting.
- type: textarea
id: description
attributes:
label: Describe the feature
placeholder: A feature X that allows to do Y
validations:
required: true
- type: textarea
id: rationale
attributes:
label: It should be implemented because
placeholder: It will allow to do Y that is needed for Z
- type: textarea
id: context
attributes:
label: Additional context
placeholder: |
Add any other context or screenshots about the feature request here.
- type: dropdown
id: assign
attributes:
label: "Would you like to work on this issue?"
options:
- "Yes"
- type: markdown
attributes:
value: |
Thanks for your suggestion! Let's see together if it can be implemented.
15 changes: 15 additions & 0 deletions .github/ISSUE_TEMPLATE/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Issues template

I created this template to help you report bugs or suggest new features more easily without having to manually write them.

If you have any questions, please submit a Pull Request (PR) or open Issues.


<img width="1163" height="364" alt="image" src="https://github.com/user-attachments/assets/125eb950-c5c1-4762-b02d-4f8fb3a5ceaf" />
<div align="center"><i>You can choose one of these three</i></div>

<img width="1992" height="1323" alt="image" src="https://github.com/user-attachments/assets/f63014ee-fac5-4c0e-b846-8f168ca42921" />
<div align="center"><i>Bug Report</i></div>

<img width="2027" height="1326" alt="image" src="https://github.com/user-attachments/assets/7ecd00a9-0457-4980-88c6-91ec849f67b0" />
<div align="center"><i>New Feature</i></div>
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Release Go Package

on:
push:
branches:
- main
- fix/download-version
- test/ci-cd
tags:
- 'v*'
pull_request:
branches: [ '**' ]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write

jobs:
test-and-release:
name: Quality & Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true

- name: Run Linter
uses: golangci/golangci-lint-action@v6
with:
version: latest

# Quick Test: Runs on any Pull Request, or during Release/Test-branch
- name: Quick Test
if: github.event_name == 'pull_request' || startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'test/ci-cd'
run: go test -v ./...

# Deep Test (-race): Runs only when PR targets main, or during Release/Test-branch
- name: Deep Test (Race Detection)
if: (github.event_name == 'pull_request' && github.base_ref == 'main') || startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'test/ci-cd'
run: go test -v -race $(go list ./... | grep -v /bench)

# Benchmark: Runs only on Releases (tags), test/ci-cd branch, or manual dispatch
- name: Run Benchmark & Capture Output
if: startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'test/ci-cd' || github.event_name == 'workflow_dispatch'
run: |
echo "BENCH_REPORT<<EOF" >> $GITHUB_ENV
go run scripts/bench_analyzer.go >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

# Prepare combined release notes
- name: Prepare Release Notes
if: startsWith(github.ref, 'refs/tags/v')
run: |
# 1. Generate standard GitHub release notes (What's Changed, Contributors, etc.)
GEN_NOTES=$(gh api repos/${{ github.repository }}/releases/generate-notes -f tag_name=${{ github.ref_name }} --jq .body)

# 2. Build the final body
echo "RELEASE_BODY<<EOF" >> $GITHUB_ENV
echo "$GEN_NOTES" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
echo "## Installation" >> $GITHUB_ENV
echo "\`\`\`bash" >> $GITHUB_ENV
echo "go get github.com/${{ github.repository }}@${{ github.ref_name }}" >> $GITHUB_ENV
echo "\`\`\`" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
echo "## Performance Benchmarks" >> $GITHUB_ENV
echo "\`\`\`text" >> $GITHUB_ENV
echo "${{ env.BENCH_REPORT }}" >> $GITHUB_ENV
echo "\`\`\`" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
name: ${{ github.ref_name }}
body: ${{ env.RELEASE_BODY }}
generate_release_notes: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/versenilvis/fuzzy

go 1.26.2
go 1.24
31 changes: 16 additions & 15 deletions scripts/bench_analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"regexp"
"strconv"
Expand All @@ -18,7 +19,7 @@ type benchResult struct {
}

func main() {
fmt.Println("Running benchmarks, please wait...")
fmt.Fprintln(os.Stderr, "Running benchmarks, please wait...")

cmd := exec.Command("go", "test", "-bench=.", "-benchmem", "./bench/...")
var out bytes.Buffer
Expand All @@ -44,24 +45,24 @@ func main() {
func parseBenchOutput(output string) []benchResult {
var results []benchResult
scanner := bufio.NewScanner(strings.NewReader(output))

// regex to parse: Name-Threads Iterations Time/op Mem/op Allocs/op
re := regexp.MustCompile(`Benchmark([\w/]+)-?\d*\s+\d+\s+([\d\.]+)\sns/op\s+([\d\.]+)\sB/op`)

descriptions := map[string]string{
"Linux100k/ascii_short": "Real-world dataset (100K files)",
"Linux100k/ascii_ext": "Extended ASCII search",
"Linux100k/path_like": "Deep nesting (/usr/lib/...)",
"Linux100k/typo": "Typo-tolerant search",
"Linux100k/long_query": "Long query pattern",
"Linux100k_NewSearcher": "Build index (~100K files)",
"Search/1000_files": "Standard workload (1K files)",
"Search/10000_files": "Medium workload (10K files)",
"Normalize": "String cleaning (ASCII)",
"LevenshteinRatio": "Zero allocation core distance",
"SearchWithCache": "Search with internal cache",
"GetBoostScores": "Ranking logic (Frecency)",
"RecordSelection": "Updating selection history",
"Linux100k/ascii_short": "Real-world dataset (100K files)",
"Linux100k/ascii_ext": "Extended ASCII search",
"Linux100k/path_like": "Deep nesting (/usr/lib/...)",
"Linux100k/typo": "Typo-tolerant search",
"Linux100k/long_query": "Long query pattern",
"Linux100k_NewSearcher": "Build index (~100K files)",
"Search/1000_files": "Standard workload (1K files)",
"Search/10000_files": "Medium workload (10K files)",
"Normalize": "String cleaning (ASCII)",
"LevenshteinRatio": "Zero allocation core distance",
"SearchWithCache": "Search with internal cache",
"GetBoostScores": "Ranking logic (Frecency)",
"RecordSelection": "Updating selection history",
}

for scanner.Scan() {
Expand Down
20 changes: 12 additions & 8 deletions tests/fuzzy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,20 +213,24 @@ func TestSearcher_EdgeCases(t *testing.T) {
s := fuzzy.NewSearcher(files)
var wg sync.WaitGroup

for range 50 {
wg.Go(func() {
for range 100 {
for range 20 {
wg.Add(1)
go func() {
defer wg.Done()
for range 50 {
s.Search("aaa")
}
})
}()
}

for range 10 {
wg.Go(func() {
for range 50 {
for range 5 {
wg.Add(1)
go func() {
defer wg.Done()
for range 20 {
s.RecordSelection("aaa", files[0])
}
})
}()
}

wg.Wait()
Expand Down
Loading