From 077a880a325599d4eebbf42cdc0c8d163890e519 Mon Sep 17 00:00:00 2001 From: OkutaniDaichi0106 <132345842+OkutaniDaichi0106@users.noreply.github.com> Date: Sun, 30 Aug 2026 17:42:57 +0900 Subject: [PATCH 1/2] chore: initialize repo environment from gomoqt and qumo - .github/: workflows (go, lint, benchmark, release, require-changelog), issue templates, PR template, dependabot, bench-report script - Root config: .golangci.yml, codecov.yml, .gitignore, .gitattributes, .dockerignore - Docs: CONTRIBUTING.md, CODE_OF_CONDUCT.md, CHANGELOG.md, README.md - Go module: github.com/qumo-dev/qumo-lb, Go 1.27.0 - magefiles/: starter build script with test, lint, fmt, vet, ci targets Co-Authored-By: Claude Code --- .dockerignore | 7 + .gitattributes | 2 + .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/bug_report.yml | 111 +++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 16 ++ .github/ISSUE_TEMPLATE/crash.yml | 60 +++++++ .github/ISSUE_TEMPLATE/feature.yml | 82 ++++++++++ .github/ISSUE_TEMPLATE/spec_discussion.yml | 86 ++++++++++ .github/dependabot.yml | 11 ++ .github/pull_request_template.md | 22 +++ .github/release.yml | 39 +++++ .github/scripts/bench-report.sh | 92 +++++++++++ .github/workflows/benchmark-label.yml | 154 ++++++++++++++++++ .github/workflows/go.yml | 92 +++++++++++ .github/workflows/lint.yml | 36 +++++ .github/workflows/release.yml | 60 +++++++ .github/workflows/require-changelog.yml | 32 ++++ .gitignore | 46 +++--- .golangci.yml | 22 +++ CHANGELOG.md | 8 + CODE_OF_CONDUCT.md | 134 ++++++++++++++++ CONTRIBUTING.md | 178 +++++++++++++++++++++ README.md | 3 + codecov.yml | 27 ++++ go.mod | 3 + magefiles/go.mod | 5 + magefiles/go.sum | 2 + magefiles/magefile.go | 33 ++++ 28 files changed, 1337 insertions(+), 27 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitattributes create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/crash.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/ISSUE_TEMPLATE/spec_discussion.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/release.yml create mode 100644 .github/scripts/bench-report.sh create mode 100644 .github/workflows/benchmark-label.yml create mode 100644 .github/workflows/go.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/require-changelog.yml create mode 100644 .golangci.yml create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 README.md create mode 100644 codecov.yml create mode 100644 go.mod create mode 100644 magefiles/go.mod create mode 100644 magefiles/go.sum create mode 100644 magefiles/magefile.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c6ed775 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +bin +coverage +cov +**/node_modules +**/*.log +**/testdata diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bb7d38f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# CI helper scripts run on Ubuntu runners โ€” keep LF regardless of checkout OS. +*.sh text eol=lf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6746951 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [qumo-dev] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..1d0b8a6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,111 @@ +name: "Bug Report" +description: "Report unexpected behavior or issues" +title: "[BUG] " +labels: ["type:bug", "status:triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Thank you for reporting this bug! Please provide detailed information. + + - type: textarea + id: description + attributes: + label: "Bug Description" + description: "Describe what happened" + placeholder: | + Example) Calling `client.Subscribe()` causes a panic + validations: + required: true + + - type: textarea + id: steps + attributes: + label: "Steps to Reproduce" + description: "Steps to reproduce the bug" + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: "Expected Behavior" + description: "What should happen" + placeholder: "Example) Successfully connect and receive data" + validations: + required: true + + - type: textarea + id: actual + attributes: + label: "Actual Behavior" + description: "What actually happened" + placeholder: "Example) panic: nil pointer dereference" + validations: + required: true + + - type: textarea + id: logs + attributes: + label: "Logs" + description: "Error logs or stack traces" + render: text + validations: + required: false + + - type: input + id: os + attributes: + label: "Operating System" + placeholder: "Example) Windows 11, macOS 14, Linux (Ubuntu 22.04)" + validations: + required: true + + - type: input + id: go_version + attributes: + label: "Go Version" + placeholder: "Example) go version go1.21.0" + validations: + required: true + + - type: input + id: project_version + attributes: + label: "Project Version" + placeholder: "Example) commit hash, tag, or branch" + validations: + required: true + + - type: textarea + id: code_sample + attributes: + label: "Minimal Reproduction Code" + description: "Minimal code that reproduces the bug" + render: go + placeholder: | + ```go + func ExampleBug() { + // Minimal code that reproduces the bug + } + ``` + validations: + required: false + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I searched for existing issues" + required: true + - label: "I can reproduce on the main branch" + required: true + - label: "I have included relevant logs" + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3d20351 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,16 @@ +contact_links: + - name: "๐Ÿ’ฌ Questions" + url: https://github.com/qumo-dev/qumo-lb/discussions + about: "Use Discussions for implementation and usage questions" + + - name: "๐Ÿ“š Documentation" + url: https://qumo-dev.github.io/qumo-lb/ + about: "Project documentation" + + - name: "๐Ÿ” Security Report" + url: https://github.com/qumo-dev/qumo-lb/security/advisories + about: "Report security vulnerabilities directly" + + - name: "๐Ÿค Contributing" + url: https://github.com/qumo-dev/qumo-lb/blob/main/CONTRIBUTING.md + about: "Please read our contributing guidelines" diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml new file mode 100644 index 0000000..85b3f78 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -0,0 +1,60 @@ +name: Crash +about: Using tsgo or the language server caused a panic +title: "" +labels: [Crash] +assignees: [] + +body: + - type: textarea + id: stack-trace + attributes: + label: Stack trace + description: Please paste the full stack trace here. + placeholder: | + [paste stack trace here] + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Describe the steps to reproduce the crash. + placeholder: | + 1. Step one + 2. Step two + 3. Step three + validations: + required: true + + - type: input + id: version + attributes: + label: Version + description: What version of tsgo or the language server are you using? + placeholder: e.g., v1.0.0 + + - type: textarea + id: environment + attributes: + label: Environment + description: Describe your environment (OS, architecture, runtime version, etc.) + placeholder: | + - OS: Windows 11 + - Architecture: x64 + - Runtime: Node.js v18.0.0 + - Other relevant details + + - type: textarea + id: logs + attributes: + label: Logs + description: If applicable, provide any relevant logs or error messages. + placeholder: | + [paste logs here] + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context about the problem here, such as what you were trying to do when the crash occurred. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..ff8fff1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,82 @@ +name: "Feature Request" +description: "Propose a new feature or improvement" +title: "[FEATURE] " +labels: ["type:feature", "status:triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Thank you for contributing! Please provide the following information. + + - type: textarea + id: overview + attributes: + label: "Overview" + description: "Briefly describe the purpose of this feature." + placeholder: | + Example: A short summary of what this feature is intended to accomplish. + validations: + required: true + + - type: textarea + id: motivation_benefits + attributes: + label: "Motivation & Benefits" + description: "Why is this feature needed, and what advantages does it bring?" + placeholder: | + Example: Explain the problem this feature solves, and what benefits it provides to users or developers. + validations: + required: true + + - type: textarea + id: use_case + attributes: + label: "Use Case" + description: "Describe how this feature would be used." + placeholder: | + Example: Provide a typical scenario where this feature would be applied. + validations: + required: true + + - type: textarea + id: proposed_solution + attributes: + label: "Proposed Solution (include Next Steps)" + description: "Provide a high-level idea of how this could be implemented, including suggested next steps." + placeholder: | + Example: Describe the approach for implementing this feature, along with any suggested next steps for discussion or prototyping. + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: "Alternatives Considered" + description: "Any other approaches you considered" + placeholder: | + Example: List any alternative solutions or approaches that were considered. + validations: + required: false + + - type: input + id: related_issues + attributes: + label: "Related issues" + description: "Please provide the issue number or URL of related issues (optional). Example: #123, https://github.com/owner/repo/issues/123" + placeholder: "#123, https://github.com/owner/repo/issues/123" + validations: + required: false + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I have searched existing issues" + required: true + - label: "I have read relevant documentation" + required: false + - label: "I can contribute to this feature" + required: false diff --git a/.github/ISSUE_TEMPLATE/spec_discussion.yml b/.github/ISSUE_TEMPLATE/spec_discussion.yml new file mode 100644 index 0000000..a585d74 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/spec_discussion.yml @@ -0,0 +1,86 @@ +name: "Specification & Protocol Discussion" +description: "Discuss protocol specifications and design" +title: "[SPEC] " +labels: ["type:discussion", "status:triage", "area:protocol"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Welcome to protocol and specification discussions. + + - type: textarea + id: topic + attributes: + label: "Discussion Topic" + description: "What specification topic do you want to discuss?" + placeholder: | + Example) About sequence number handling in SUBSCRIBE frames + validations: + required: true + + - type: textarea + id: current_behavior + attributes: + label: "Current Spec/Implementation" + description: "Describe the current specification or implementation" + placeholder: | + Example) RFC sections or current code implementation + validations: + required: true + + - type: textarea + id: question_proposal + attributes: + label: "Question/Proposal" + description: "Your question or improvement proposal" + placeholder: | + Example) Is this approach feasible while maintaining compatibility? + validations: + required: true + + - type: textarea + id: references + attributes: + label: "References" + description: "Links to RFCs, docs, or other specs" + placeholder: | + - [RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000) + - [MoQ Draft](https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport) + validations: + required: false + + - type: textarea + id: implications + attributes: + label: "Implementation Implications" + description: "How this affects implementation or compatibility" + placeholder: | + - Compatibility impact + - Performance implications + - Impact on other components + validations: + required: false + + - type: checkboxes + id: tags + attributes: + label: "Related Areas" + options: + - label: "Frame Design" + - label: "Error Handling" + - label: "Flow Control" + - label: "Connection Management" + - label: "Security" + - label: "Interoperability" + + - type: checkboxes + id: checklist + attributes: + label: "Checklist" + options: + - label: "I have read relevant specs" + required: true + - label: "I checked existing discussions" + required: false diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..cd88554 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "gomod" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..9b8bbd3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,22 @@ +## Description + +What does this PR do? + +## Related Issue + +Closes # + +## Changes + +- +- + +## Testing + +How was this tested? + +## Checklist + +- [ ] Comments added for complex logic +- [ ] Documentation updated if needed +- [ ] Tests added/updated diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..e1f1213 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,39 @@ +# Configuration for GitHub's auto-generated release notes. +# +# Used by `gh release create --generate-notes` (see .github/workflows/release.yml) +# and the web UI's "Generate release notes" button. Maps merged-PR labels to +# release-note sections. +changelog: + exclude: + labels: + - no-changelog + - duplicate + - invalid + - wontfix + categories: + - title: ๐Ÿ”’ Security + labels: + - security + - title: ๐Ÿš€ Features + labels: + - type:feature + - enhancement + - title: โšก Performance + labels: + - performance + - performance-check + - title: ๐Ÿ› Bug Fixes + labels: + - bug + - title: ๐Ÿ“ฆ Dependencies + labels: + - dependencies + - title: ๐Ÿ“š Documentation + labels: + - documentation + - title: ๐Ÿงช Tests + labels: + - tests + - title: Other Changes + labels: + - "*" diff --git a/.github/scripts/bench-report.sh b/.github/scripts/bench-report.sh new file mode 100644 index 0000000..f57e615 --- /dev/null +++ b/.github/scripts/bench-report.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# Build a readable benchmark-comparison PR comment from a benchstat baseline and +# the PR's results. Produces, in order: +# 1. a one-line summary: regression/improvement counts (or "No significant +# changes"); +# 2. a filtered "significant changes" view (only changed benchmarks, with env +# metadata once); +# 3. the full benchstat table, collapsed, for audit. +# +# Usage: bench-report.sh +# Requires: benchstat on PATH (go install golang.org/x/perf/cmd/benchstat@latest). +# +# Called by .github/workflows/benchmark-label.yml. Kept as a standalone script +# (rather than inline in the workflow) so it is readable and independently +# testable: `bench-report.sh base.txt new.txt out.md`. +set -euo pipefail + +baseline="${1:?usage: bench-report.sh }" +new="${2:?usage: bench-report.sh }" +out="${3:?usage: bench-report.sh }" + +work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT +full="$work/benchstat-full.txt"; filt="$work/benchstat.txt" + +# Full benchstat across all metrics (sec/op, B/op, allocs/op). Default alpha=0.05; +# allocs/op deltas are deterministic -> always significant regardless of -count. +benchstat "$baseline" "$new" > "$full" || true + +# Readable subset: keep a metric section only if it has >=1 significant +# per-benchmark change; within kept sections drop the non-significant ("~") +# rows, the geomean row, and benchstat footnotes. Env metadata printed once. +awk ' + function printBlock() { + if (outCount == 0) printf "%s", envBlock; else print "" + printf "%s", buf; outCount++ + } + BEGIN { outCount = 0 } + /^(goos|goarch|pkg|cpu):/ { envBlock = envBlock $0 "\n"; next } + /~/ { next } + /need >= |are equal|must be >0/ { next } + /^[[:space:]]*$/ { if (emit) printBlock(); buf = ""; emit = 0; next } + { buf = buf $0 "\n"; if ($0 ~ / [+-][0-9]+\.[0-9]+% / && $0 !~ /^geomean/) emit = 1 } + END { if (emit) printBlock() } +' "$full" > "$filt" + +# Count significant per-benchmark regressions (+) and improvements (-), excluding +# the geomean rows so the summary isn't double-counted. +regress=$(grep -E ' \+[0-9]+\.[0-9]+% ' "$full" | grep -vc '^geomean' || true) +improv=$(grep -E ' -[0-9]+\.[0-9]+% ' "$full" | grep -vc '^geomean' || true) + +{ + echo "" + echo "## ๐ŸŽ๏ธ Benchmark comparison (main โ†’ PR)" + echo + echo "Microbenchmarks \`-benchtime=50ms -count=10\` (turnaround over precision; significance from -count). \`allocs/op\` and \`B/op\` are deterministic โ€” any delta there is real. \`sec/op\` is a quick signal; re-run locally with \`-benchtime=1s -count=10+\` for significance. In the table, \`+\` = regression, \`-\` = improvement, \`~\` = not significant." + echo +} > "$out" + +summary="" +[ "$regress" -gt 0 ] && summary="โš ๏ธ **${regress} regression(s)**" +if [ "$improv" -gt 0 ]; then + [ -n "$summary" ] && summary="$summary โ€ข " + summary="${summary}โœ… **${improv} improvement(s)**" +fi +if [ -z "$summary" ]; then + echo "โœ… **No significant changes** โ€” all benchmarks within measurement noise." >> "$out" +else + echo "$summary" >> "$out" +fi +echo >> "$out" + +# Significant changes shown prominently (open); full table collapsed for audit. +if [ "$regress" -gt 0 ] || [ "$improv" -gt 0 ]; then + { + echo "
" + echo "๐Ÿ“Š Significant changes (main โ†’ PR, filtered)" + echo + echo '```text' + cat "$filt" + echo '```' + echo "
" + } >> "$out" +fi +{ + echo "
" + echo "๐Ÿ”Ž Full benchstat output (all benchmarks, all metrics)" + echo + echo '```text' + cat "$full" + echo '```' + echo "
" +} >> "$out" diff --git a/.github/workflows/benchmark-label.yml b/.github/workflows/benchmark-label.yml new file mode 100644 index 0000000..c1dd946 --- /dev/null +++ b/.github/workflows/benchmark-label.yml @@ -0,0 +1,154 @@ +# On-demand micro-benchmark for performance-focused PRs. +# +# Triggered when the `performance-check` label is added to a pull request (or by +# manual dispatch). For every Go package the PR touches, it benchmarks BOTH the +# PR head and the PR's base SHA back-to-back IN THE SAME JOB (same runner, same +# flags, seconds apart) and compares them with benchstat. The result is posted +# -- and updated in place -- as a PR comment. +# +# Why base+PR in one job (not a pre-captured baseline artifact): a baseline +# captured by a separate, earlier run drifts -- different runner hardware/load, +# different -benchtime/-count, or a stale commit -- which surfaces as spurious +# uniform "changes" even for code-identical PRs (we saw ~22% on every benchmark +# for a CI-only PR). Running both sides in the same job eliminates that drift so +# the diff reflects the code, not the environment. +# +# Only packages whose *.go changed are benchmarked, so a PR that touches no +# implementation (docs/CI-only) runs no benchmarks and posts no comment. +# +# Turnaround over precision: -benchtime=50ms -count=10. Statistical significance +# comes from -count (10 samples); -benchtime is kept low because the suite +# is large and shared-runner wall time is ~2-3x variable, so a higher benchtime +# blows the timeout (count=4/100ms already timed out on a slow runner). 50ms +# still runs 10k+ iterations/sample, so per-sample means stay stable. allocs/op +# and B/op are deterministic regardless of these flags -> the reliable signal; +# sec/op is a quick indicator (re-run locally with -benchtime=1s -count=10+). +# count=10: benchstat needs >=6 samples for a CI / meaningful p-values; at +# count=4 it flags every non-identical median at p=0.029 (spurious "significant" +# deltas). The slow real-QUIC integration benchmarks self-skip under -short. +name: Benchmark (performance-check) + +on: + pull_request: + types: [labeled] + workflow_dispatch: {} + +permissions: + contents: read + pull-requests: write # post/update the benchstat comparison as a PR comment + +jobs: + benchmark: + if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'performance-check' + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + # Same flags for base and PR so the comparison is like-for-like. + BENCH_FLAGS: "-benchtime=50ms -count=10" + steps: + - name: Checkout PR head (full history for base diff + worktree) + uses: actions/checkout@v4 + with: + ref: ${{ env.HEAD_SHA }} + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: go.mod + cache: true + + - name: Install benchstat + run: go install golang.org/x/perf/cmd/benchstat@latest + + - name: Detect changed Go packages + id: changed + run: | + set -euo pipefail + # Only benchmark packages whose *.go actually changed; a CI/docs-only + # PR then has nothing to compare and posts no benchmark comment. + git diff --name-only --diff-filter=ACMR "$BASE_SHA" "$HEAD_SHA" -- '*.go' \ + | xargs -r -n1 dirname | sort -u > pkgs.txt + if [ -s pkgs.txt ]; then + echo "any=true" >> "$GITHUB_OUTPUT" + echo "Changed Go packages:" + cat pkgs.txt + else + echo "any=false" >> "$GITHUB_OUTPUT" + echo "No changed Go packages -- nothing to benchmark." + fi + + - name: Checkout base into a worktree + if: steps.changed.outputs.any == 'true' + run: | + # Separate worktree so the base and PR source trees don't clobber each + # other. The Go module/build caches are global, so both builds reuse them. + git worktree add "$RUNNER_TEMP/base" "$BASE_SHA" + echo "BASE_DIR=$RUNNER_TEMP/base" >> "$GITHUB_ENV" + + - name: Run base benchmarks + if: steps.changed.outputs.any == 'true' + working-directory: ${{ env.BASE_DIR }} + run: | + : > "$GITHUB_WORKSPACE/base.txt" + while IFS= read -r pkg; do + [ -d "./$pkg" ] || continue + echo "::group::Base benchmark: $pkg" + # || true: a build/run failure in one package must not abort the rest. + go test -run='^$' -bench=. -short -benchmem $BENCH_FLAGS -timeout=15m "./$pkg" \ + >> "$GITHUB_WORKSPACE/base.txt" 2>&1 || true + echo "::endgroup::" + done < "$GITHUB_WORKSPACE/pkgs.txt" + + - name: Run PR benchmarks + if: steps.changed.outputs.any == 'true' + run: | + : > pr.txt + while IFS= read -r pkg; do + [ -d "./$pkg" ] || continue + echo "::group::PR benchmark: $pkg" + go test -run='^$' -bench=. -short -benchmem $BENCH_FLAGS -timeout=15m "./$pkg" \ + >> pr.txt 2>&1 || true + echo "::endgroup::" + done < pkgs.txt + + - name: Compare and build comment + if: steps.changed.outputs.any == 'true' + continue-on-error: true + run: | + bash .github/scripts/bench-report.sh base.txt pr.txt benchstat-comment.md + echo '::group::benchstat comparison (base -> PR)' + cat benchstat-comment.md + echo '::endgroup::' + + - name: Post or update comment + if: steps.changed.outputs.any == 'true' && github.event_name == 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + PR: ${{ github.event.pull_request.number }} + run: | + # Update the existing bench-report comment in place (found by marker) + # so re-runs don't stack duplicates; create it on first run. + marker="" + comment_id=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR/comments" \ + --paginate --jq ".[] | select(.body | contains(\"$marker\")) | .id" | head -n1) + if [ -n "$comment_id" ]; then + gh api -X PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$comment_id" \ + -f body="$(cat benchstat-comment.md)" >/dev/null + else + gh pr comment "$PR" --body-file benchstat-comment.md + fi + + - name: Upload benchmark output + if: always() && steps.changed.outputs.any == 'true' + uses: actions/upload-artifact@v4 + with: + name: bench-perfcheck-pr-${{ github.event.pull_request.number || 'manual' }} + path: | + base.txt + pr.txt + benchstat-comment.md + if-no-files-found: ignore + retention-days: 30 diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..895aadd --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,92 @@ +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: Go + +on: + push: + branches: ["main"] + tags: ["v*"] + pull_request: + paths: + - "**.go" + - "go.mod" + - "go.sum" + - "magefiles/**" + - ".github/workflows/go.yml" + workflow_dispatch: {} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: go.mod + + - name: Test + run: go test -v ./... + + - name: Test with coverage + run: go test -coverprofile=coverage.out -covermode=atomic -coverpkg=./... ./... + + - name: Upload coverage report + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.out + flags: go + name: go-coverage + fail_ci_if_error: false + verbose: true + + # Race detection requires CGO + a C compiler (gcc). The ubuntu runner has + # gcc; local dev machines without gcc cannot run -race. We isolate it in + # its own job so the rest of CI is unaffected by CGO_ENABLED. + race: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: go.mod + + - name: Test with -race + env: + # -race needs CGO and a C compiler; ubuntu-latest ships gcc. + CGO_ENABLED: "1" + run: | + go test -race -count=1 -timeout=10m ./... + + # Slow real-QUIC integration benchmarks. Runs the FULL benchmark suite WITHOUT + # -short, so the benchmarks that self-skip under testing.Short() actually run + # here. Each op is a multi-second aggregate (frames/sec, MB/s) stable across + # samples, so -benchtime=1x is appropriate (unlike the microbenchmarks above). + # Runs only on push (main/tags) and manual dispatch โ€” NOT on PRs โ€” because it + # costs ~10-19 runner-minutes. Uploaded for trend archival only; no benchstat gate. + benchmark-integration: + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: go.mod + + - name: Run integration benchmarks + run: | + go test -run='^$' -bench=. -benchmem -benchtime=1x -count=5 -timeout=25m ./... | tee bench-integration.txt + + - name: Upload integration bench output + uses: actions/upload-artifact@v4 + with: + name: bench-integration + path: bench-integration.txt + retention-days: 90 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..9f8f5d9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,36 @@ +name: Linter + +on: + pull_request: + branches: ["main"] + paths: + - "**.go" + - "go.mod" + - "go.sum" + - ".golangci.yml" + - ".github/workflows/lint.yml" + workflow_dispatch: {} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + checks: write + contents: read + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: go.mod + + - name: Lint + uses: reviewdog/action-golangci-lint@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + level: warning + reporter: github-pr-review + go_version: ^1.27 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..02653b0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +# Creates a GitHub Release when a version tag is pushed. +# +# qumo-lb is a Go library: the tag itself is the release artifact (consumed via +# `go get github.com/qumo-dev/qumo-lb@vX.Y.Z`), so there is nothing to compile. +# Release notes come from GitHub's auto-generator (`--generate-notes`), grouped +# into sections by the label configuration in .github/release.yml. +# +# Also runnable via workflow_dispatch (e.g. to re-publish a release or rebuild +# its notes after fixing .github/release.yml) without re-pushing the tag. +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + tag: + description: 'Tag to publish (must already exist, e.g. v0.1.0)' + required: true + +permissions: + contents: write # required to create / edit the release + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve tag + id: tag + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + tag="${{ inputs.tag }}" + else + tag="${GITHUB_REF_NAME}" + fi + echo "tag=$tag" >> "$GITHUB_OUTPUT" + echo "Publishing release for $tag" + + - name: Create or update GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -e + tag="${{ steps.tag.outputs.tag }}" + if gh release view "$tag" >/dev/null 2>&1; then + echo "Release $tag already exists; regenerating notes." + gh release edit "$tag" --generate-notes + else + # --verify-tag fails the job if the tag does not point at a real commit. + gh release create "$tag" \ + --generate-notes \ + --verify-tag \ + --title "$tag" + fi diff --git a/.github/workflows/require-changelog.yml b/.github/workflows/require-changelog.yml new file mode 100644 index 0000000..069fca0 --- /dev/null +++ b/.github/workflows/require-changelog.yml @@ -0,0 +1,32 @@ +name: "Require CHANGELOG Update" + +on: + pull_request: + types: [opened, edited, synchronize, reopened, labeled, unlabeled] + +jobs: + check-changelog: + runs-on: ubuntu-latest + + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + fetch-depth: 0 # full history + + - name: Skip CHANGELOG check (no-changelog label) + if: ${{ contains(github.event.pull_request.labels.*.name, 'no-changelog') }} + run: | + echo "Skipping CHANGELOG requirement: 'no-changelog' label is present." + + - name: Verify CHANGELOG.md modification + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-changelog') }} + run: | + # look for any diff lines affecting CHANGELOG.md + if git diff --name-only "origin/${{ github.base_ref }}"...HEAD | grep -q '^CHANGELOG\.md$'; then + echo "CHANGELOG.md has been updated." + else + echo "::error file=CHANGELOG.md::Pull request must include a change to CHANGELOG.md" \ + "(add a new entry, or apply the 'no-changelog' label for small/non-feature tasks)."; + exit 1 + fi diff --git a/.gitignore b/.gitignore index aaadf73..dd49e7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,24 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib +# IDE +**/.vscode +**/.github/prompts -# Test binary, built with `go test -c` -*.test +# Dev modules +**/_vendor +**/node_modules +**/.serena -# Code coverage profiles and other test artifacts -*.out -coverage.* -*.coverprofile -profile.cov +# Build staff +**/dist/ +**/*.exe -# Dependency directories (remove the comment below to include it) -# vendor/ +# Coverage +coverage* +coverage_message +coverage_protocol +**/coverage/ -# Go workspace file -go.work -go.work.sum +# Profiles +**.prof -# env file -.env - -# Editor/IDE -# .idea/ -# .vscode/ +# Local Environment +**.pem diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..d6a6f1b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,22 @@ +version: "2" + +# Minimal, modern golangci-lint config. +# Keep the config simple: enable a few high-value linters and +# keep revive rules for exported symbols and package comments. +run: + timeout: 10m + +linters: + default: none + enable: + - govet + - gosec + - staticcheck + - revive + settings: + gosec: + excludes: + - G115 # integer overflow conversions โ€” too noisy for wire-protocol code +# Note: keep any revive custom rules in a separate file if needed. +# For simplicity we rely on revive's defaults here; add settings later +# if you want stricter exported/package comment checks. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15a61af --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f5f393f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,134 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement via +[GitHub Issues](https://github.com/qumo-dev/qumo-lb/issues) or by contacting +the project maintainers directly. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f96c279 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,178 @@ +# Contributing to qumo-lb + +Thank you for your interest in contributing to qumo-lb! We welcome contributions from the community. + +## Code of Conduct + +This project follows a [Code of Conduct](./CODE_OF_CONDUCT.md) to ensure a welcoming environment for all contributors. + +## Getting Started + +### Prerequisites + +Before you begin, ensure you have the following installed: +- Go 1.27.0 or later +- [Mage](https://magefile.org/) build tool (install with `go install github.com/magefile/mage@latest`) +- Git + +### Development Setup + +1. Fork and clone the repository: + ```bash + git clone https://github.com/your-username/qumo-lb.git + cd qumo-lb + ``` + +2. Install dependencies: + ```bash + go mod download + ``` + +3. Install Mage build tool: + ```bash + go install github.com/magefile/mage@latest + ``` + +4. Verify your setup: + ```bash + mage test + ``` + +## Development Workflow + +### 1. Choose an Issue + +- Check existing [issues](https://github.com/qumo-dev/qumo-lb/issues) for good first issues +- Look for issues labeled `good first issue` or `help wanted` +- Comment on the issue to indicate you're working on it + +### 2. Create a Branch + +Create a feature branch from `main`: +```bash +git checkout -b feature/your-feature-name +# or +git checkout -b fix/issue-number-description +``` + +### 3. Make Changes + +- Write clear, focused commits +- Follow Go coding standards +- Add tests for new functionality +- Update documentation as needed + +### 4. Testing + +Run tests before submitting: +```bash +# Run all tests +mage test + +# Run specific package tests +go test ./... + +# Run with race detection +go test -race ./... + +# Run benchmarks +go test -bench=. ./... +``` + +### 5. Code Quality + +Ensure your code meets our standards: +```bash +# Format code +mage fmt + +# Run linter (requires golangci-lint) +mage lint +``` + +## Coding Standards + +### Go Style Guide + +- Follow the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) +- Use `go fmt` for formatting +- Write clear, concise function and variable names +- Add comments for exported functions and types +- Keep functions small and focused + +### Documentation Guidelines + +All exported symbols (functions, types, constants, variables) must be documented with godoc comments: + +- **Start with the symbol name**: Comments should begin with the name of the item being documented +- **Use complete sentences**: Write clear, grammatically correct sentences +- **Be concise but clear**: Explain what, not how (code shows how) +- **Package documentation**: Add a `doc.go` file or package comment in any `.go` file + +Example: +```go +// Package example provides utilities for demonstration purposes. +package example + +// Config holds configuration options for the service. +type Config struct { + Timeout time.Duration +} + +// NewConfig creates a new Config with default values. +func NewConfig() *Config { + return &Config{ + Timeout: 30 * time.Second, + } +} +``` + +### Commit Messages + +Use clear, descriptive commit messages: +``` +type(scope): description + +[optional body] + +[optional footer] +``` + +Types: +- `feat`: New features +- `fix`: Bug fixes +- `docs`: Documentation +- `style`: Code style changes +- `refactor`: Code refactoring +- `test`: Testing +- `chore`: Maintenance + +### Pull Request Guidelines + +When submitting a pull request: + +1. **Title**: Use a clear, descriptive title +2. **Description**: Explain what the PR does and why +3. **Tests**: Ensure all tests pass +4. **Documentation**: Update docs if needed +5. **Breaking Changes**: Clearly mark any breaking changes +6. **Changelog**: Add or update an entry in `CHANGELOG.md` describing your changes. A GitHub workflow enforces this requirement and will block the PR if `CHANGELOG.md` isn't modified. + +### Testing Requirements + +- Add unit tests for new functionality +- Ensure existing tests still pass +- Test edge cases and error conditions +- Consider integration tests for complex features + +## Communication + +- **Issues**: For bug reports and feature requests +- **Discussions**: For questions and general discussion +- **Pull Requests**: For code contributions + +## License + +By contributing to this project, you agree that your contributions will be licensed under the same license as the project (see LICENSE file). + +Thank you for contributing to qumo-lb! ๐Ÿš€ diff --git a/README.md b/README.md new file mode 100644 index 0000000..03858ba --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# qumo-lb + +A Go load-balancer library for the MoQ Transport protocol. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..4ca17bb --- /dev/null +++ b/codecov.yml @@ -0,0 +1,27 @@ +ignore: + # Build tooling is not library code. + - "magefiles/" + +flag_management: + individual_flags: true + +flags: + go: + paths: + - . + carryforward: false + +coverage: + status: + project: + go: + target: 75% + threshold: 2% + flags: + - go + patch: + go: + target: 70% + threshold: 5% + flags: + - go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4ef3d95 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/qumo-dev/qumo-lb + +go 1.27.0 diff --git a/magefiles/go.mod b/magefiles/go.mod new file mode 100644 index 0000000..816989c --- /dev/null +++ b/magefiles/go.mod @@ -0,0 +1,5 @@ +module github.com/qumo-dev/qumo-lb/magefiles + +go 1.27.0 + +require github.com/magefile/mage v1.15.0 diff --git a/magefiles/go.sum b/magefiles/go.sum new file mode 100644 index 0000000..4ee1b87 --- /dev/null +++ b/magefiles/go.sum @@ -0,0 +1,2 @@ +github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= +github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= diff --git a/magefiles/magefile.go b/magefiles/magefile.go new file mode 100644 index 0000000..22e19ac --- /dev/null +++ b/magefiles/magefile.go @@ -0,0 +1,33 @@ +// Package main is the mage build script for qumo-lb. +package main + +import ( + "github.com/magefile/mage/mg" + "github.com/magefile/mage/sh" +) + +// Test runs all Go tests. +func Test() error { + return sh.RunV("go", "test", "./...") +} + +// Lint runs golangci-lint. +func Lint() error { + return sh.RunV("golangci-lint", "run", "./...") +} + +// Fmt formats Go code. +func Fmt() error { + return sh.RunV("go", "fmt", "./...") +} + +// Vet runs go vet. +func Vet() error { + return sh.RunV("go", "vet", "./...") +} + +// CI runs the full CI pipeline locally. +func CI() error { + mg.SerialDeps(Test, Lint, Vet) + return nil +} From 6679bb55f2ba92d21004834180555c284a4e05c7 Mon Sep 17 00:00:00 2001 From: OkutaniDaichi0106 <132345842+OkutaniDaichi0106@users.noreply.github.com> Date: Sun, 30 Aug 2026 21:26:32 +0900 Subject: [PATCH 2/2] fix: address code-review findings - go.yml: merge double test run into single -v -coverprofile pass - go.yml: add -short to race job (skip slow integration tests) - lint.yml: remove fetch-depth: 0 (lint only needs current state) - benchmark-label.yml: gate benchstat install on changed packages Co-Authored-By: Claude Code --- .github/workflows/benchmark-label.yml | 7 ++++--- .github/workflows/go.yml | 7 ++----- .github/workflows/lint.yml | 2 -- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/benchmark-label.yml b/.github/workflows/benchmark-label.yml index c1dd946..3880e42 100644 --- a/.github/workflows/benchmark-label.yml +++ b/.github/workflows/benchmark-label.yml @@ -60,9 +60,6 @@ jobs: go-version-file: go.mod cache: true - - name: Install benchstat - run: go install golang.org/x/perf/cmd/benchstat@latest - - name: Detect changed Go packages id: changed run: | @@ -80,6 +77,10 @@ jobs: echo "No changed Go packages -- nothing to benchmark." fi + - name: Install benchstat + if: steps.changed.outputs.any == 'true' + run: go install golang.org/x/perf/cmd/benchstat@latest + - name: Checkout base into a worktree if: steps.changed.outputs.any == 'true' run: | diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 895aadd..6220dab 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -27,11 +27,8 @@ jobs: with: go-version-file: go.mod - - name: Test - run: go test -v ./... - - name: Test with coverage - run: go test -coverprofile=coverage.out -covermode=atomic -coverpkg=./... ./... + run: go test -v -coverprofile=coverage.out -covermode=atomic -coverpkg=./... ./... - name: Upload coverage report uses: codecov/codecov-action@v5 @@ -61,7 +58,7 @@ jobs: # -race needs CGO and a C compiler; ubuntu-latest ships gcc. CGO_ENABLED: "1" run: | - go test -race -count=1 -timeout=10m ./... + go test -race -short -count=1 -timeout=10m ./... # Slow real-QUIC integration benchmarks. Runs the FULL benchmark suite WITHOUT # -short, so the benchmarks that self-skip under testing.Short() actually run diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9f8f5d9..814eb9b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,8 +20,6 @@ jobs: steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v4 with: