From 77b4821568f61bf13ddb9498353bc3e74db84f5e Mon Sep 17 00:00:00 2001 From: verse91 Date: Wed, 6 May 2026 22:45:34 +0700 Subject: [PATCH] feat: ci/cd and issue template --- .github/ISSUE_TEMPLATE/BugReport.yml | 51 +++++++++++++++ .github/ISSUE_TEMPLATE/NewFeature.yml | 36 +++++++++++ .github/ISSUE_TEMPLATE/README.md | 15 +++++ .github/workflows/release.yml | 91 +++++++++++++++++++++++++++ go.mod | 2 +- scripts/bench_analyzer.go | 31 ++++----- tests/fuzzy_test.go | 20 +++--- 7 files changed, 222 insertions(+), 24 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/BugReport.yml create mode 100644 .github/ISSUE_TEMPLATE/NewFeature.yml create mode 100644 .github/ISSUE_TEMPLATE/README.md create mode 100644 .github/workflows/release.yml diff --git a/.github/ISSUE_TEMPLATE/BugReport.yml b/.github/ISSUE_TEMPLATE/BugReport.yml new file mode 100644 index 0000000..c6dbede --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BugReport.yml @@ -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. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/NewFeature.yml b/.github/ISSUE_TEMPLATE/NewFeature.yml new file mode 100644 index 0000000..e284c58 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/NewFeature.yml @@ -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. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/README.md b/.github/ISSUE_TEMPLATE/README.md new file mode 100644 index 0000000..622d9f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/README.md @@ -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. + + +image +
You can choose one of these three
+ +image +
Bug Report
+ +image +
New Feature
\ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c7436f2 --- /dev/null +++ b/.github/workflows/release.yml @@ -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<> $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<> $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 }} diff --git a/go.mod b/go.mod index 4745352..0242d01 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/versenilvis/fuzzy -go 1.26.2 +go 1.24 diff --git a/scripts/bench_analyzer.go b/scripts/bench_analyzer.go index 03e77c4..9c1edcc 100644 --- a/scripts/bench_analyzer.go +++ b/scripts/bench_analyzer.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "os" "os/exec" "regexp" "strconv" @@ -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 @@ -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() { diff --git a/tests/fuzzy_test.go b/tests/fuzzy_test.go index ff79259..913cb3c 100644 --- a/tests/fuzzy_test.go +++ b/tests/fuzzy_test.go @@ -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()