@aaronshaf/ger 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.ast-grep/rules/no-as-casting.yml +13 -0
  2. package/.eslintrc.js +12 -0
  3. package/.github/workflows/ci-simple.yml +53 -0
  4. package/.github/workflows/ci.yml +171 -0
  5. package/.github/workflows/claude-code-review.yml +78 -0
  6. package/.github/workflows/claude.yml +64 -0
  7. package/.github/workflows/dependency-update.yml +84 -0
  8. package/.github/workflows/release.yml +166 -0
  9. package/.github/workflows/security-scan.yml +113 -0
  10. package/.github/workflows/security.yml +96 -0
  11. package/.husky/pre-commit +16 -0
  12. package/.husky/pre-push +25 -0
  13. package/.lintstagedrc.json +6 -0
  14. package/.tool-versions +1 -0
  15. package/CLAUDE.md +103 -0
  16. package/DEVELOPMENT.md +361 -0
  17. package/LICENSE +21 -0
  18. package/README.md +325 -0
  19. package/bin/ger +3 -0
  20. package/biome.json +36 -0
  21. package/bun.lock +688 -0
  22. package/bunfig.toml +8 -0
  23. package/oxlint.json +24 -0
  24. package/package.json +55 -0
  25. package/scripts/check-coverage.ts +69 -0
  26. package/scripts/check-file-size.ts +38 -0
  27. package/scripts/fix-test-mocks.ts +55 -0
  28. package/src/api/gerrit.ts +466 -0
  29. package/src/cli/commands/abandon.ts +65 -0
  30. package/src/cli/commands/comment.ts +460 -0
  31. package/src/cli/commands/comments.ts +85 -0
  32. package/src/cli/commands/diff.ts +71 -0
  33. package/src/cli/commands/incoming.ts +226 -0
  34. package/src/cli/commands/init.ts +164 -0
  35. package/src/cli/commands/mine.ts +115 -0
  36. package/src/cli/commands/open.ts +57 -0
  37. package/src/cli/commands/review.ts +593 -0
  38. package/src/cli/commands/setup.ts +230 -0
  39. package/src/cli/commands/show.ts +303 -0
  40. package/src/cli/commands/status.ts +35 -0
  41. package/src/cli/commands/workspace.ts +200 -0
  42. package/src/cli/index.ts +420 -0
  43. package/src/prompts/default-review.md +80 -0
  44. package/src/prompts/system-inline-review.md +88 -0
  45. package/src/prompts/system-overall-review.md +152 -0
  46. package/src/schemas/config.test.ts +245 -0
  47. package/src/schemas/config.ts +75 -0
  48. package/src/schemas/gerrit.ts +455 -0
  49. package/src/services/ai-enhanced.ts +167 -0
  50. package/src/services/ai.ts +182 -0
  51. package/src/services/config.test.ts +414 -0
  52. package/src/services/config.ts +206 -0
  53. package/src/test-utils/mock-generator.ts +73 -0
  54. package/src/utils/comment-formatters.ts +153 -0
  55. package/src/utils/diff-context.ts +103 -0
  56. package/src/utils/diff-formatters.ts +141 -0
  57. package/src/utils/formatters.ts +85 -0
  58. package/src/utils/message-filters.ts +26 -0
  59. package/src/utils/shell-safety.ts +117 -0
  60. package/src/utils/status-indicators.ts +100 -0
  61. package/src/utils/url-parser.test.ts +123 -0
  62. package/src/utils/url-parser.ts +91 -0
  63. package/tests/abandon.test.ts +163 -0
  64. package/tests/ai-service.test.ts +489 -0
  65. package/tests/comment-batch-advanced.test.ts +431 -0
  66. package/tests/comment-gerrit-api-compliance.test.ts +414 -0
  67. package/tests/comment.test.ts +707 -0
  68. package/tests/comments.test.ts +323 -0
  69. package/tests/config-service-simple.test.ts +100 -0
  70. package/tests/diff.test.ts +419 -0
  71. package/tests/helpers/config-mock.ts +27 -0
  72. package/tests/incoming.test.ts +357 -0
  73. package/tests/interactive-incoming.test.ts +173 -0
  74. package/tests/mine.test.ts +318 -0
  75. package/tests/mocks/fetch-mock.ts +139 -0
  76. package/tests/mocks/msw-handlers.ts +80 -0
  77. package/tests/open.test.ts +233 -0
  78. package/tests/review.test.ts +669 -0
  79. package/tests/setup.ts +13 -0
  80. package/tests/show.test.ts +439 -0
  81. package/tests/unit/schemas/gerrit.test.ts +85 -0
  82. package/tests/unit/test-utils/mock-generator.test.ts +154 -0
  83. package/tests/unit/utils/comment-formatters.test.ts +415 -0
  84. package/tests/unit/utils/diff-context.test.ts +171 -0
  85. package/tests/unit/utils/diff-formatters.test.ts +165 -0
  86. package/tests/unit/utils/formatters.test.ts +411 -0
  87. package/tests/unit/utils/message-filters.test.ts +227 -0
  88. package/tests/unit/utils/prompt-helpers.test.ts +175 -0
  89. package/tests/unit/utils/shell-safety.test.ts +230 -0
  90. package/tests/unit/utils/status-indicators.test.ts +137 -0
  91. package/tsconfig.json +40 -0
@@ -0,0 +1,13 @@
1
+ id: no-as-casting
2
+ language: typescript
3
+ rule:
4
+ any:
5
+ - pattern: $EXPR as $TYPE
6
+ not:
7
+ any:
8
+ - pattern: $EXPR as const
9
+ - pattern: $EXPR as unknown
10
+ - pattern: ($EXPR as unknown) as $TYPE2
11
+ - pattern: $EXPR as unknown as $TYPE2
12
+ message: Type casting with 'as' is not allowed. Use proper typing or 'as unknown' if necessary.
13
+ severity: error
package/.eslintrc.js ADDED
@@ -0,0 +1,12 @@
1
+ export default {
2
+ env: {
3
+ browser: true,
4
+ es2022: true,
5
+ },
6
+ extends: "eslint:recommended",
7
+ parserOptions: {
8
+ ecmaVersion: "latest",
9
+ sourceType: "module",
10
+ },
11
+ rules: {},
12
+ };
@@ -0,0 +1,53 @@
1
+ name: CI (Simple)
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ name: Test and Build
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Setup Bun
22
+ uses: oven-sh/setup-bun@v1
23
+ with:
24
+ bun-version: latest
25
+
26
+ - name: Cache dependencies
27
+ uses: actions/cache@v4
28
+ with:
29
+ path: |
30
+ ~/.bun/install/cache
31
+ node_modules
32
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
33
+ restore-keys: |
34
+ ${{ runner.os }}-bun-
35
+
36
+ - name: Install dependencies
37
+ run: bun install --frozen-lockfile
38
+
39
+ - name: Run TypeScript check
40
+ run: bun run typecheck
41
+
42
+ - name: Run linting
43
+ run: bun run lint
44
+
45
+ - name: Run tests with coverage
46
+ run: bun run test:coverage
47
+
48
+ - name: Check coverage (non-blocking)
49
+ run: bun run test:coverage:check || echo "Coverage check completed with warnings"
50
+ continue-on-error: true
51
+
52
+ - name: Build check
53
+ run: bun run build
@@ -0,0 +1,171 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ # Fast checks that should run first
15
+ typecheck:
16
+ name: TypeScript Check
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Setup Bun
23
+ uses: oven-sh/setup-bun@v1
24
+ with:
25
+ bun-version: "1.2.17"
26
+
27
+ - name: Cache dependencies
28
+ uses: actions/cache@v4
29
+ with:
30
+ path: |
31
+ ~/.bun/install/cache
32
+ node_modules
33
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
34
+ restore-keys: |
35
+ ${{ runner.os }}-bun-
36
+
37
+ - name: Install dependencies
38
+ run: bun install --frozen-lockfile
39
+
40
+ - name: TypeScript check
41
+ run: bun run typecheck
42
+
43
+ lint:
44
+ name: Lint
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - name: Checkout code
48
+ uses: actions/checkout@v4
49
+
50
+ - name: Setup Bun
51
+ uses: oven-sh/setup-bun@v1
52
+ with:
53
+ bun-version: "1.2.17"
54
+
55
+ - name: Cache dependencies
56
+ uses: actions/cache@v4
57
+ with:
58
+ path: |
59
+ ~/.bun/install/cache
60
+ node_modules
61
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
62
+ restore-keys: |
63
+ ${{ runner.os }}-bun-
64
+
65
+ - name: Install dependencies
66
+ run: bun install --frozen-lockfile
67
+
68
+ - name: Run oxlint
69
+ run: bun run lint
70
+
71
+
72
+ # Test jobs that depend on the fast checks passing
73
+ test:
74
+ name: Unit Tests
75
+ runs-on: ubuntu-latest
76
+ needs: [typecheck, lint]
77
+ steps:
78
+ - name: Checkout code
79
+ uses: actions/checkout@v4
80
+
81
+ - name: Setup Bun
82
+ uses: oven-sh/setup-bun@v1
83
+ with:
84
+ bun-version: "1.2.17"
85
+
86
+ - name: Cache dependencies
87
+ uses: actions/cache@v4
88
+ with:
89
+ path: |
90
+ ~/.bun/install/cache
91
+ node_modules
92
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
93
+ restore-keys: |
94
+ ${{ runner.os }}-bun-
95
+
96
+ - name: Install dependencies
97
+ run: bun install --frozen-lockfile
98
+
99
+ - name: Run tests with coverage
100
+ run: bun run test:coverage
101
+
102
+ - name: Check coverage threshold
103
+ run: bun run test:coverage:check
104
+ continue-on-error: true
105
+
106
+ # Build job that runs after all checks pass
107
+ build:
108
+ name: Build
109
+ runs-on: ubuntu-latest
110
+ needs: [test]
111
+ steps:
112
+ - name: Checkout code
113
+ uses: actions/checkout@v4
114
+
115
+ - name: Setup Bun
116
+ uses: oven-sh/setup-bun@v1
117
+ with:
118
+ bun-version: "1.2.17"
119
+
120
+ - name: Cache dependencies
121
+ uses: actions/cache@v4
122
+ with:
123
+ path: |
124
+ ~/.bun/install/cache
125
+ node_modules
126
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
127
+ restore-keys: |
128
+ ${{ runner.os }}-bun-
129
+
130
+ - name: Install dependencies
131
+ run: bun install --frozen-lockfile
132
+
133
+ - name: Build check
134
+ run: bun run build
135
+
136
+ # Complete check that mirrors pre-commit hooks
137
+ all-checks:
138
+ name: All Checks (Mirror of pre-commit)
139
+ runs-on: ubuntu-latest
140
+ needs: [build]
141
+ steps:
142
+ - name: Checkout code
143
+ uses: actions/checkout@v4
144
+
145
+ - name: Setup Bun
146
+ uses: oven-sh/setup-bun@v1
147
+ with:
148
+ bun-version: "1.2.17"
149
+
150
+ - name: Cache dependencies
151
+ uses: actions/cache@v4
152
+ with:
153
+ path: |
154
+ ~/.bun/install/cache
155
+ node_modules
156
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
157
+ restore-keys: |
158
+ ${{ runner.os }}-bun-
159
+
160
+ - name: Install dependencies
161
+ run: bun install --frozen-lockfile
162
+
163
+ - name: Run individual checks (safer than check:all)
164
+ run: |
165
+ echo "Running typecheck..."
166
+ bun run typecheck
167
+ echo "Running lint..."
168
+ bun run lint
169
+ echo "Running tests with coverage..."
170
+ bun run test:coverage
171
+ echo "All checks completed successfully!"
@@ -0,0 +1,78 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@beta
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+
40
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
41
+ # model: "claude-opus-4-20250514"
42
+
43
+ # Direct prompt for automated review (no @claude mention needed)
44
+ direct_prompt: |
45
+ Please review this pull request and provide feedback on:
46
+ - Code quality and best practices
47
+ - Potential bugs or issues
48
+ - Performance considerations
49
+ - Security concerns
50
+ - Test coverage
51
+
52
+ Be constructive and helpful in your feedback.
53
+
54
+ # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
55
+ # use_sticky_comment: true
56
+
57
+ # Optional: Customize review based on file types
58
+ # direct_prompt: |
59
+ # Review this PR focusing on:
60
+ # - For TypeScript files: Type safety and proper interface usage
61
+ # - For API endpoints: Security, input validation, and error handling
62
+ # - For React components: Performance, accessibility, and best practices
63
+ # - For tests: Coverage, edge cases, and test quality
64
+
65
+ # Optional: Different prompts for different authors
66
+ # direct_prompt: |
67
+ # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
68
+ # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
69
+ # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
70
+
71
+ # Optional: Add specific tools for running tests or linting
72
+ # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
73
+
74
+ # Optional: Skip review for certain conditions
75
+ # if: |
76
+ # !contains(github.event.pull_request.title, '[skip-review]') &&
77
+ # !contains(github.event.pull_request.title, '[WIP]')
78
+
@@ -0,0 +1,64 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@beta
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
44
+ # model: "claude-opus-4-20250514"
45
+
46
+ # Optional: Customize the trigger phrase (default: @claude)
47
+ # trigger_phrase: "/claude"
48
+
49
+ # Optional: Trigger when specific user is assigned to an issue
50
+ # assignee_trigger: "claude-bot"
51
+
52
+ # Optional: Allow Claude to run specific commands
53
+ # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
54
+
55
+ # Optional: Add custom instructions for Claude to customize its behavior for your project
56
+ # custom_instructions: |
57
+ # Follow our coding standards
58
+ # Ensure all new code has tests
59
+ # Use TypeScript for new files
60
+
61
+ # Optional: Custom environment variables for Claude
62
+ # claude_env: |
63
+ # NODE_ENV: test
64
+
@@ -0,0 +1,84 @@
1
+ name: Dependency Updates
2
+
3
+ on:
4
+ schedule:
5
+ # Run weekly on Mondays at 9 AM UTC
6
+ - cron: '0 9 * * 1'
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+ pull-requests: write
12
+
13
+ jobs:
14
+ update-dependencies:
15
+ name: Update Dependencies
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+ with:
21
+ token: ${{ secrets.GITHUB_TOKEN }}
22
+
23
+ - name: Setup Bun
24
+ uses: oven-sh/setup-bun@v1
25
+ with:
26
+ bun-version: latest
27
+
28
+ - name: Cache dependencies
29
+ uses: actions/cache@v4
30
+ with:
31
+ path: |
32
+ ~/.bun/install/cache
33
+ node_modules
34
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
35
+ restore-keys: |
36
+ ${{ runner.os }}-bun-
37
+
38
+ - name: Update dependencies
39
+ run: |
40
+ # Update all dependencies
41
+ bun update
42
+
43
+ # Check if there are any changes
44
+ if git diff --quiet bun.lockb package.json; then
45
+ echo "No dependency updates available"
46
+ echo "has_updates=false" >> $GITHUB_ENV
47
+ else
48
+ echo "Dependencies have been updated"
49
+ echo "has_updates=true" >> $GITHUB_ENV
50
+ fi
51
+
52
+ - name: Run tests after update
53
+ if: env.has_updates == 'true'
54
+ run: |
55
+ bun install --frozen-lockfile
56
+ bun run check:all
57
+
58
+ - name: Create Pull Request
59
+ if: env.has_updates == 'true'
60
+ uses: peter-evans/create-pull-request@v5
61
+ with:
62
+ token: ${{ secrets.GITHUB_TOKEN }}
63
+ commit-message: 'chore: update dependencies'
64
+ title: 'chore: automated dependency updates'
65
+ body: |
66
+ ## Automated Dependency Updates
67
+
68
+ This PR contains automated dependency updates.
69
+
70
+ ### Changes
71
+ - Updated dependencies to their latest versions
72
+ - All tests and checks are passing
73
+
74
+ ### Review Checklist
75
+ - [ ] Check for any breaking changes in the updated dependencies
76
+ - [ ] Verify that all tests are still passing
77
+ - [ ] Review any new security advisories
78
+
79
+ 🤖 This PR was created automatically by GitHub Actions.
80
+ branch: chore/update-dependencies
81
+ delete-branch: true
82
+ labels: |
83
+ dependencies
84
+ automated
@@ -0,0 +1,166 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: 'Version to release (e.g., v1.0.0)'
11
+ required: true
12
+ type: string
13
+
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.ref }}
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ # Run the same checks as CI before release
20
+ pre-release-checks:
21
+ name: Pre-release Checks
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - name: Checkout code
25
+ uses: actions/checkout@v4
26
+
27
+ - name: Setup Bun
28
+ uses: oven-sh/setup-bun@v1
29
+ with:
30
+ bun-version: latest
31
+
32
+ - name: Cache dependencies
33
+ uses: actions/cache@v4
34
+ with:
35
+ path: |
36
+ ~/.bun/install/cache
37
+ node_modules
38
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
39
+ restore-keys: |
40
+ ${{ runner.os }}-bun-
41
+
42
+ - name: Install dependencies
43
+ run: bun install --frozen-lockfile
44
+
45
+ - name: Run all checks
46
+ run: bun run check:all
47
+
48
+ # Build for multiple platforms
49
+ build-release:
50
+ name: Build Release
51
+ runs-on: ${{ matrix.os }}
52
+ needs: [pre-release-checks]
53
+ strategy:
54
+ matrix:
55
+ os: [ubuntu-latest, macos-latest, windows-latest]
56
+ include:
57
+ - os: ubuntu-latest
58
+ target: linux
59
+ - os: macos-latest
60
+ target: darwin
61
+ - os: windows-latest
62
+ target: windows
63
+ steps:
64
+ - name: Checkout code
65
+ uses: actions/checkout@v4
66
+
67
+ - name: Setup Bun
68
+ uses: oven-sh/setup-bun@v1
69
+ with:
70
+ bun-version: latest
71
+
72
+ - name: Cache dependencies
73
+ uses: actions/cache@v4
74
+ with:
75
+ path: |
76
+ ~/.bun/install/cache
77
+ node_modules
78
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
79
+ restore-keys: |
80
+ ${{ runner.os }}-bun-
81
+
82
+ - name: Install dependencies
83
+ run: bun install --frozen-lockfile
84
+
85
+ - name: Build for ${{ matrix.target }}
86
+ run: bun run build
87
+
88
+ - name: Create release archive (Unix)
89
+ if: matrix.os != 'windows-latest'
90
+ run: |
91
+ tar -czf gi-${{ matrix.target }}.tar.gz -C dist .
92
+
93
+ - name: Create release archive (Windows)
94
+ if: matrix.os == 'windows-latest'
95
+ run: |
96
+ Compress-Archive -Path dist\* -DestinationPath gi-${{ matrix.target }}.zip
97
+
98
+ - name: Upload release artifacts (Unix)
99
+ if: matrix.os != 'windows-latest'
100
+ uses: actions/upload-artifact@v4
101
+ with:
102
+ name: gi-${{ matrix.target }}
103
+ path: gi-${{ matrix.target }}.tar.gz
104
+ retention-days: 30
105
+
106
+ - name: Upload release artifacts (Windows)
107
+ if: matrix.os == 'windows-latest'
108
+ uses: actions/upload-artifact@v4
109
+ with:
110
+ name: gi-${{ matrix.target }}
111
+ path: gi-${{ matrix.target }}.zip
112
+ retention-days: 30
113
+
114
+ # Create GitHub release
115
+ create-release:
116
+ name: Create Release
117
+ runs-on: ubuntu-latest
118
+ needs: [build-release]
119
+ permissions:
120
+ contents: write
121
+ steps:
122
+ - name: Checkout code
123
+ uses: actions/checkout@v4
124
+ with:
125
+ fetch-depth: 0
126
+
127
+ - name: Download all artifacts
128
+ uses: actions/download-artifact@v4
129
+ with:
130
+ path: artifacts
131
+
132
+ - name: Generate release notes
133
+ id: release-notes
134
+ run: |
135
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
136
+ VERSION="${{ github.event.inputs.version }}"
137
+ else
138
+ VERSION="${GITHUB_REF#refs/tags/}"
139
+ fi
140
+
141
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
142
+
143
+ # Generate changelog since last tag
144
+ LAST_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
145
+ if [[ -n "$LAST_TAG" ]]; then
146
+ echo "## Changes since $LAST_TAG" > release_notes.md
147
+ git log --pretty=format:"- %s (%an)" "$LAST_TAG"..HEAD >> release_notes.md
148
+ else
149
+ echo "## Initial Release" > release_notes.md
150
+ echo "First release of the Gerrit CLI tool with comprehensive security improvements." >> release_notes.md
151
+ fi
152
+
153
+ - name: Create Release
154
+ uses: softprops/action-gh-release@v1
155
+ with:
156
+ tag_name: ${{ steps.release-notes.outputs.version }}
157
+ name: Release ${{ steps.release-notes.outputs.version }}
158
+ body_path: release_notes.md
159
+ files: |
160
+ artifacts/gi-linux/gi-linux.tar.gz
161
+ artifacts/gi-darwin/gi-darwin.tar.gz
162
+ artifacts/gi-windows/gi-windows.zip
163
+ draft: false
164
+ prerelease: false
165
+ env:
166
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}