-
Notifications
You must be signed in to change notification settings - Fork 0
chore: standardize CI tooling with lefthook, goreleaser, and reusable workflows #5
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| name: PR | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, edited, synchronize, reopened] | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| title: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Validate PR title follows Conventional Commits | ||
| env: | ||
| TITLE: ${{ github.event.pull_request.title }} | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| if echo "$TITLE" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?(!)?: .+"; then | ||
| echo "PR title is valid: $TITLE" | ||
| exit 0 | ||
| fi | ||
|
|
||
| BODY=$(cat <<'COMMENT' | ||
| ### ⚠️ Invalid PR Title | ||
|
|
||
| PR title must follow the **Conventional Commits** format since we use squash merge: | ||
|
|
||
| ``` | ||
| <type>[optional scope][!]: <description> | ||
| ``` | ||
|
|
||
| **Allowed types:** `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `build`, `ci`, `perf`, `revert` | ||
|
|
||
| **Examples:** | ||
| - `feat: add new feature` | ||
| - `fix(api): resolve null pointer` | ||
| - `feat!: breaking change` | ||
| - `chore(deps): update dependencies` | ||
| COMMENT | ||
| ) | ||
|
|
||
| # Post comment on PR | ||
| gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \ | ||
| -X POST -f body="$BODY" | ||
|
|
||
| echo "::error::PR title must follow Conventional Commits format" | ||
| exit 1 | ||
|
|
||
| review: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: AxeForging/reviewforge@main | ||
| with: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| AI_PROVIDER: gemini | ||
| AI_MODEL: gemini-2.5-flash | ||
| AI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | ||
| SHOW_TOKEN_USAGE: true | ||
| INCREMENTAL: false | ||
| REVIEW_RULES: concise | ||
|
|
||
| validate: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: AxeForging/structlint@main | ||
| with: | ||
| config: .structlint.yaml | ||
| comment-on-pr: "true" | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,8 +4,9 @@ on: | |
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: 'Tag to release (e.g. v1.0.0)' | ||
| required: true | ||
| description: 'Release tag (leave empty for auto-bump from conventional commits)' | ||
| required: false | ||
| type: string | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
@@ -14,39 +15,52 @@ jobs: | |
| release: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@v4 | ||
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: '1.24' | ||
| check-latest: true | ||
| cache: true | ||
|
|
||
| - name: Run tests | ||
| run: go test ./... | ||
| run: go test ./... -v | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [CRITICAL] These |
||
|
|
||
| - name: Build binaries | ||
| run: VERSION=${{ github.event.inputs.tag }} make build | ||
| - name: Determine version | ||
| id: version | ||
| uses: AxeForging/releaseforge@main | ||
| with: | ||
| command: bump | ||
|
|
||
| - name: Create archives | ||
| - name: Set tag | ||
| id: tag | ||
| run: | | ||
| cd dist | ||
| for f in *; do | ||
| if [[ "$f" == *.exe ]]; then | ||
| zip "${f%.exe}.zip" "$f" | ||
| else | ||
| tar czf "$f.tar.gz" "$f" | ||
| fi | ||
| done | ||
| cd .. | ||
|
|
||
| - name: Create Release | ||
| uses: softprops/action-gh-release@v1 | ||
| if [ -n "${{ inputs.tag }}" ]; then | ||
| echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "tag=${{ steps.version.outputs.next-version }}" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Generate release notes | ||
| id: notes | ||
| uses: AxeForging/releaseforge@main | ||
| with: | ||
| command: generate | ||
| api-key: ${{ secrets.GEMINI_API_KEY }} | ||
|
|
||
| - name: Create and push tag | ||
| run: | | ||
| echo "Releasing ${{ steps.tag.outputs.tag }}" | ||
| git tag ${{ steps.tag.outputs.tag }} | ||
| git push origin ${{ steps.tag.outputs.tag }} | ||
|
|
||
| - name: Run GoReleaser | ||
| uses: goreleaser/goreleaser-action@v6 | ||
| with: | ||
| tag_name: ${{ github.event.inputs.tag }} | ||
| files: | | ||
| dist/*.tar.gz | ||
| dist/*.zip | ||
| draft: false | ||
| prerelease: false | ||
| generate_release_notes: true | ||
| version: latest | ||
| args: release --clean --release-notes ${{ steps.notes.outputs.release-notes }} | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| name: ReviewForge | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| ai-provider: | ||
| description: "AI provider: openai, anthropic, gemini" | ||
| type: string | ||
| default: "gemini" | ||
| ai-model: | ||
| description: "AI model to use" | ||
| type: string | ||
| default: "gemini-2.5-flash" | ||
| incremental: | ||
| description: "Only review new changes since last bot review" | ||
| type: boolean | ||
| default: false | ||
| show-token-usage: | ||
| description: "Append AI token usage metrics to the review summary" | ||
| type: boolean | ||
| default: false | ||
| persona: | ||
| description: "Reviewer persona: bob, robert, maya, eli" | ||
| type: string | ||
| default: "" | ||
| review-rules: | ||
| description: "Built-in comment rules preset: concise, thorough" | ||
| type: string | ||
| default: "concise" | ||
| max-comments: | ||
| description: "Maximum number of line comments (0 = unlimited)" | ||
| type: string | ||
| default: "5" | ||
| exclude-patterns: | ||
| description: "Comma-separated glob patterns to exclude" | ||
| type: string | ||
| default: "**/*.lock,**/*.json,**/*.md" | ||
| secrets: | ||
| ai_api_key: | ||
| description: "API key for the chosen AI provider" | ||
| required: true | ||
| github_token: | ||
| description: "GitHub token for API access" | ||
| required: false | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| review: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: AxeForging/reviewforge@main | ||
| with: | ||
| GITHUB_TOKEN: ${{ secrets.github_token || github.token }} | ||
| AI_PROVIDER: ${{ inputs.ai-provider }} | ||
| AI_MODEL: ${{ inputs.ai-model }} | ||
| AI_API_KEY: ${{ secrets.ai_api_key }} | ||
| INCREMENTAL: ${{ inputs.incremental }} | ||
| SHOW_TOKEN_USAGE: ${{ inputs.show-token-usage }} | ||
| PERSONA: ${{ inputs.persona }} | ||
| REVIEW_RULES: ${{ inputs.review-rules }} | ||
| MAX_COMMENTS: ${{ inputs.max-comments }} | ||
| EXCLUDE_PATTERNS: ${{ inputs.exclude-patterns }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| # GoReleaser configuration for ReviewForge | ||
| version: 2 | ||
|
|
||
| before: | ||
| hooks: | ||
| - go mod tidy | ||
|
|
||
| builds: | ||
| - env: | ||
| - CGO_ENABLED=0 | ||
| goos: | ||
| - linux | ||
| - darwin | ||
| - windows | ||
| goarch: | ||
| - amd64 | ||
| - arm64 | ||
| - 386 | ||
| - arm | ||
| ldflags: | ||
| - -s -w | ||
| - -X main.Version={{.Version}} | ||
| - -X main.BuildTime={{.Date}} | ||
| - -X main.GitCommit={{.FullCommit}} | ||
| ignore: | ||
| - goos: windows | ||
| goarch: arm | ||
|
|
||
| archives: | ||
| - formats: | ||
| - tar.gz | ||
| name_template: "reviewforge-{{ .Os }}-{{ .Arch }}" | ||
| files: | ||
| - README.md | ||
| - LICENSE | ||
| format_overrides: | ||
| - goos: windows | ||
| formats: | ||
| - zip | ||
|
|
||
| checksum: | ||
| name_template: checksums.txt | ||
|
|
||
| snapshot: | ||
| version_template: "{{ incpatch .Version }}-next" | ||
|
|
||
| changelog: | ||
| sort: asc | ||
| filters: | ||
| exclude: | ||
| - '^docs:' | ||
| - '^test:' | ||
|
|
||
| release: | ||
| github: | ||
| owner: AxeForging | ||
| name: reviewforge | ||
| draft: false | ||
| prerelease: auto | ||
| name_template: "Release {{ .Tag }}" | ||
| footer: | | ||
| ## Installation | ||
|
|
||
| ### Go Install | ||
| ```bash | ||
| go install github.com/AxeForging/reviewforge@{{ .Tag }} | ||
| ``` | ||
|
|
||
| ### Linux/macOS (AMD64) | ||
| ```bash | ||
| curl -L https://github.com/AxeForging/reviewforge/releases/download/{{ .Tag }}/reviewforge-linux-amd64.tar.gz | tar xz | ||
| chmod +x reviewforge-linux-amd64 | ||
| sudo mv reviewforge-linux-amd64 /usr/local/bin/reviewforge | ||
| ``` | ||
|
|
||
| ### Linux/macOS (ARM64) | ||
| ```bash | ||
| curl -L https://github.com/AxeForging/reviewforge/releases/download/{{ .Tag }}/reviewforge-linux-arm64.tar.gz | tar xz | ||
| chmod +x reviewforge-linux-arm64 | ||
| sudo mv reviewforge-linux-arm64 /usr/local/bin/reviewforge | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[WARNING] These
git tagandgit pushcommands are redundant and can conflict withgoreleaser-action. GoReleaser is designed to handle the creation and pushing of tags as part of its release process. It's best to remove these lines and let GoReleaser manage the tagging.