@boringstudio_org/gitea-mcp 1.7.1 → 1.9.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.
@@ -1,4 +1,4 @@
1
- name: Release and Publish
1
+ name: Auto Release
2
2
 
3
3
  on:
4
4
  push:
@@ -8,42 +8,59 @@ on:
8
8
  jobs:
9
9
  release:
10
10
  runs-on: ubuntu-latest
11
- if: "!contains(github.event.head_commit.message, 'chore(release)')"
12
11
  steps:
13
- - name: Checkout
14
- uses: actions/checkout@v4
12
+ - uses: actions/checkout@v4
15
13
  with:
16
14
  fetch-depth: 0
17
- token: ${{ secrets.RELEASE_TOKEN }}
18
15
 
19
- - name: Checkout branch
16
+ - name: Check if release is needed
17
+ id: check
20
18
  run: |
21
- git checkout main
22
- git pull origin main
19
+ VERSION=$(node -p "require('./package.json').version")
20
+ TAG="v$VERSION"
21
+ if git rev-parse "$TAG" >/dev/null 2>&1; then
22
+ echo "Tag $TAG already exists. Skipping release."
23
+ echo "release=false" >> $GITHUB_OUTPUT
24
+ else
25
+ echo "New version $VERSION detected. Proceeding with release."
26
+ echo "release=true" >> $GITHUB_OUTPUT
27
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
28
+ echo "tag=$TAG" >> $GITHUB_OUTPUT
29
+ fi
23
30
 
24
31
  - name: Setup Node.js
32
+ if: steps.check.outputs.release == 'true'
25
33
  uses: actions/setup-node@v4
26
34
  with:
27
- node-version: '24'
35
+ node-version: '24.14.0'
28
36
  registry-url: 'https://registry.npmjs.org'
29
37
 
30
- - name: Configure Git
38
+ - name: Install & Publish
39
+ if: steps.check.outputs.release == 'true'
31
40
  run: |
32
- git config user.name "Gitea Actions"
33
- git config user.email "sgmakgg@gmail.com"
41
+ npm ci
42
+ npm publish
43
+ env:
44
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
34
45
 
35
- - name: Install dependencies
36
- run: npm ci
46
+ - name: Create & Push Tag
47
+ if: steps.check.outputs.release == 'true'
48
+ env:
49
+ TAG: ${{ steps.check.outputs.tag }}
50
+ TOKEN: ${{ secrets.RENOVATE_TOKEN }}
51
+ CF_ID: ${{ secrets.CF_CLIENT_ID }}
52
+ CF_SECRET: ${{ secrets.CF_CLIENT_SECRET }}
53
+ run: |
54
+ git config user.name "Gitea Actions"
55
+ git config user.email "actions@boringstudio.by"
37
56
 
38
- - name: Run standard-version
39
- run: npm run release
57
+ # Configure Cloudflare Access Headers
58
+ git config --global http.extraHeader "CF-Access-Client-Id: $CF_ID"
59
+ git config --global --add http.extraHeader "CF-Access-Client-Secret: $CF_SECRET"
40
60
 
41
- - name: Push changes
42
- run: git push --follow-tags origin main
43
- env:
44
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
61
+ # Configure Auth
62
+ git remote set-url origin https://$TOKEN@git.boringstudio.by/BoringStudio/mcp-gitea.git
45
63
 
46
- - name: Publish to NPM
47
- run: npm publish
48
- env:
49
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
64
+ # Create and Push Tag
65
+ git tag $TAG
66
+ git push origin $TAG
@@ -0,0 +1,611 @@
1
+ name: "🔒 Mandatory Security Check"
2
+
3
+ on:
4
+ workflow_call:
5
+ pull_request:
6
+ push:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ # 1. Check Changes (Smart Skip)
15
+ changes:
16
+ runs-on: "ubuntu-latest"
17
+ outputs:
18
+ js: ${{ steps.diff.outputs.js }}
19
+ php: ${{ steps.diff.outputs.php }}
20
+ docker: ${{ steps.diff.outputs.docker }}
21
+ shell: ${{ steps.diff.outputs.shell }}
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0
27
+ token: ${{ secrets.GITHUB_TOKEN }}
28
+
29
+ - name: Check modified files
30
+ id: diff
31
+ run: |
32
+ if [ "${{ github.event_name }}" == "pull_request" ]; then
33
+ BASE=${{ github.event.pull_request.base.sha }}
34
+ HEAD=${{ github.event.pull_request.head.sha }}
35
+ else
36
+ BASE=${{ github.event.before }}
37
+ HEAD=${{ github.sha }}
38
+ fi
39
+
40
+ # Handle first commit or force push
41
+ if [ -z "$BASE" ] || [ "$BASE" == "0000000000000000000000000000000000000000" ]; then
42
+ BASE=$(git rev-parse HEAD~1 2>/dev/null || echo $HEAD)
43
+ fi
44
+
45
+ echo "Checking diff between $BASE and $HEAD"
46
+ DIFF=$(git diff --name-only $BASE $HEAD)
47
+ echo "$DIFF"
48
+
49
+ # JS/TS
50
+ if echo "$DIFF" | grep -qE "\.(js|ts|tsx|jsx|json)$"; then
51
+ echo "js=true" >> $GITHUB_OUTPUT
52
+ else
53
+ echo "js=false" >> $GITHUB_OUTPUT
54
+ fi
55
+
56
+ # PHP
57
+ if echo "$DIFF" | grep -qE "\.(php|json|lock)$"; then
58
+ echo "php=true" >> $GITHUB_OUTPUT
59
+ else
60
+ echo "php=false" >> $GITHUB_OUTPUT
61
+ fi
62
+
63
+ # Docker
64
+ if echo "$DIFF" | grep -qE "Dockerfile"; then
65
+ echo "docker=true" >> $GITHUB_OUTPUT
66
+ else
67
+ echo "docker=false" >> $GITHUB_OUTPUT
68
+ fi
69
+
70
+ # Shell
71
+ if echo "$DIFF" | grep -qE "\.sh$"; then
72
+ echo "shell=true" >> $GITHUB_OUTPUT
73
+ else
74
+ echo "shell=false" >> $GITHUB_OUTPUT
75
+ fi
76
+
77
+ # 2. Gitleaks: Secrets Detection (Gatekeeper)
78
+ gitleaks:
79
+ runs-on: "ubuntu-latest"
80
+ outputs:
81
+ log: ${{ steps.scan.outputs.log }}
82
+ steps:
83
+ - name: Checkout code
84
+ uses: actions/checkout@v4
85
+ with:
86
+ fetch-depth: 0
87
+ token: ${{ secrets.GITHUB_TOKEN }}
88
+
89
+ - name: 🧹 Gitleaks (Run & Report)
90
+ id: scan
91
+ run: |
92
+ C_NAME="gitleaks-${{ github.run_id }}"
93
+ docker rm -f $C_NAME 2>/dev/null || true
94
+
95
+ # Use custom config if exists, otherwise fallback to default
96
+ CONFIG_PATH=".gitleaks.toml"
97
+ CONFIG_FLAG=""
98
+ if [ -f "$CONFIG_PATH" ]; then
99
+ CONFIG_FLAG="--config=$CONFIG_PATH"
100
+ echo "Using custom gitleaks config: $CONFIG_PATH"
101
+ else
102
+ echo "Custom gitleaks config not found, using default rules."
103
+ fi
104
+
105
+ docker create --name $C_NAME -w /code zricethezav/gitleaks:v8.30.0 detect --source=. $CONFIG_FLAG --verbose --redact --no-banner
106
+ docker cp . $C_NAME:/code
107
+ docker start -a $C_NAME > gitleaks.log 2>&1 || EXIT=$?
108
+ sed -i 's/\x1b\[[0-9;]*m//g' gitleaks.log
109
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
110
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
111
+ cat gitleaks.log | tail -c 10000 >> $GITHUB_OUTPUT
112
+ echo '' >> $GITHUB_OUTPUT
113
+ echo 'EOF' >> $GITHUB_OUTPUT
114
+ fi
115
+ docker rm -f $C_NAME
116
+ exit ${EXIT:-0}
117
+
118
+ # --- Sequential Jobs ---
119
+
120
+ # 3. Semgrep: SAST
121
+ semgrep:
122
+ runs-on: "ubuntu-latest"
123
+ needs: [gitleaks, changes]
124
+ outputs:
125
+ log: ${{ steps.scan.outputs.log }}
126
+ steps:
127
+ - name: Checkout code
128
+ uses: actions/checkout@v4
129
+ with:
130
+ token: ${{ secrets.GITHUB_TOKEN }}
131
+
132
+ - name: Checkout Custom Rules
133
+ uses: actions/checkout@v4
134
+ with:
135
+ repository: BoringStudio/.gitea
136
+ path: .gitea-config
137
+ sparse-checkout: .gitea/semgrep-rules
138
+ token: ${{ secrets.RENOVATE_TOKEN }}
139
+
140
+ - name: 🔬 Semgrep (Run & Report)
141
+ id: scan
142
+ run: |
143
+ set +e
144
+ C_NAME="semgrep-${{ github.run_id }}"
145
+ docker rm -f $C_NAME 2>/dev/null || true
146
+ # Create container
147
+ docker create --name $C_NAME -w /src returntocorp/semgrep:1.151.0 semgrep scan --config=p/default --config=p/typescript --config=p/nodejsscan --config=p/php --config=p/docker --config=p/owasp-top-ten --config=.gitea-config/.gitea/semgrep-rules --exclude='node_modules/' --exclude='vendor/' --exclude='.strapi/' --exclude='dist/' --exclude='build/' --exclude='wp-admin/' --exclude='wp-includes/' --exclude='wordpress/wp-content/plugins/' --exclude='wordpress/wp-content/themes/' --exclude='tests/' --exclude='*_test.go' --error --verbose
148
+
149
+ # Copy files into container explicitly
150
+ docker cp . $C_NAME:/src/
151
+ if [ -d ".gitea-config" ]; then
152
+ docker cp .gitea-config $C_NAME:/src/
153
+ fi
154
+
155
+ # Run and capture output
156
+ docker start -a $C_NAME > semgrep.log 2>&1
157
+ EXIT=$?
158
+ sed -i 's/\x1b\[[0-9;]*m//g' semgrep.log
159
+
160
+ if [ "$EXIT" -ne 0 ]; then
161
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
162
+ cat semgrep.log | tail -c 10000 >> $GITHUB_OUTPUT
163
+ echo '' >> $GITHUB_OUTPUT
164
+ echo 'EOF' >> $GITHUB_OUTPUT
165
+ fi
166
+ docker rm -f $C_NAME
167
+ exit $EXIT
168
+
169
+ # 4. Hadolint: Dockerfile Linting
170
+ hadolint:
171
+ runs-on: "ubuntu-latest"
172
+ needs: [semgrep, changes]
173
+ if: needs.changes.outputs.docker == 'true'
174
+ outputs:
175
+ log: ${{ steps.scan.outputs.log }}
176
+ steps:
177
+ - name: Checkout code
178
+ uses: actions/checkout@v4
179
+ with:
180
+ token: ${{ secrets.GITHUB_TOKEN }}
181
+
182
+ - name: 🐳 Hadolint (Run & Report)
183
+ id: scan
184
+ run: |
185
+ C_NAME="hadolint-${{ github.run_id }}"
186
+ docker rm -f $C_NAME 2>/dev/null || true
187
+ docker create --name $C_NAME -w /code hadolint/hadolint:latest-debian /bin/bash -c "{ find . -name 'Dockerfile*' -not -path '*/.*' -print0 | xargs -0 -r hadolint; }"
188
+ docker cp . $C_NAME:/code
189
+ docker start -a $C_NAME > hadolint.log 2>&1 || EXIT=$?
190
+ sed -i 's/\x1b\[[0-9;]*m//g' hadolint.log
191
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
192
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
193
+ cat hadolint.log | tail -c 10000 >> $GITHUB_OUTPUT
194
+ echo '' >> $GITHUB_OUTPUT
195
+ echo 'EOF' >> $GITHUB_OUTPUT
196
+ fi
197
+ docker rm -f $C_NAME
198
+ exit ${EXIT:-0}
199
+
200
+ # 5. ShellCheck: Bash Script Linting
201
+ shellcheck:
202
+ runs-on: "ubuntu-latest"
203
+ needs: [hadolint, changes]
204
+ if: needs.changes.outputs.shell == 'true'
205
+ outputs:
206
+ log: ${{ steps.scan.outputs.log }}
207
+ steps:
208
+ - name: Checkout code
209
+ uses: actions/checkout@v4
210
+ with:
211
+ token: ${{ secrets.GITHUB_TOKEN }}
212
+
213
+ - name: 🐚 ShellCheck (Run & Report)
214
+ id: scan
215
+ run: |
216
+ C_NAME="shellcheck-${{ github.run_id }}"
217
+ docker rm -f $C_NAME 2>/dev/null || true
218
+ docker create --name $C_NAME -w /code koalaman/shellcheck-alpine:v0.11.0 /bin/sh -c "{ find . -name '*.sh' -not -path '*/.*' -print0 | xargs -0 -r shellcheck --color=always; }"
219
+ docker cp . $C_NAME:/code
220
+ docker start -a $C_NAME > shellcheck.log 2>&1 || EXIT=$?
221
+ sed -i 's/\x1b\[[0-9;]*m//g' shellcheck.log
222
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
223
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
224
+ cat shellcheck.log | tail -c 10000 >> $GITHUB_OUTPUT
225
+ echo '' >> $GITHUB_OUTPUT
226
+ echo 'EOF' >> $GITHUB_OUTPUT
227
+ fi
228
+ docker rm -f $C_NAME
229
+ exit ${EXIT:-0}
230
+
231
+ # 6. Checkov: IaC Security
232
+ checkov-scan:
233
+ runs-on: "ubuntu-latest"
234
+ needs: [shellcheck]
235
+ outputs:
236
+ log: ${{ steps.scan.outputs.log }}
237
+ steps:
238
+ - name: Checkout code
239
+ uses: actions/checkout@v4
240
+ with:
241
+ token: ${{ secrets.GITHUB_TOKEN }}
242
+
243
+ - name: 🏗️ Checkov (Run & Report)
244
+ id: scan
245
+ run: |
246
+ C_NAME="checkov-${{ github.run_id }}"
247
+ docker rm -f $C_NAME 2>/dev/null || true
248
+ docker create --name $C_NAME -w /code bridgecrew/checkov:3.2.502 /bin/bash -c "{ checkov -d . --quiet --compact --skip-check CKV_DOCKER_2,CKV_DOCKER_3; }"
249
+ docker cp . $C_NAME:/code
250
+ docker start -a $C_NAME > checkov.log 2>&1 || EXIT=$?
251
+ sed -i 's/\x1b\[[0-9;]*m//g' checkov.log
252
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
253
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
254
+ cat checkov.log | tail -c 10000 >> $GITHUB_OUTPUT
255
+ echo '' >> $GITHUB_OUTPUT
256
+ echo 'EOF' >> $GITHUB_OUTPUT
257
+ fi
258
+ docker rm -f $C_NAME
259
+ exit ${EXIT:-0}
260
+
261
+ # 7. Trivy: Dependencies & Misconfig
262
+ trivy:
263
+ runs-on: "ubuntu-latest"
264
+ needs: [checkov-scan]
265
+ outputs:
266
+ log: ${{ steps.scan.outputs.log }}
267
+ steps:
268
+ - name: Checkout code
269
+ uses: actions/checkout@v4
270
+ with:
271
+ fetch-depth: 0
272
+ token: ${{ secrets.GITHUB_TOKEN }}
273
+
274
+ - name: Checkout Custom Rules
275
+ uses: actions/checkout@v4
276
+ with:
277
+ repository: BoringStudio/.gitea
278
+ path: .gitea-config
279
+ sparse-checkout: .gitea/trivy.yaml
280
+ token: ${{ secrets.RENOVATE_TOKEN }}
281
+
282
+ - name: Cache Trivy DB
283
+ uses: actions/cache@v4
284
+ with:
285
+ path: .trivy-cache
286
+ key: trivy-db-${{ github.run_id }}
287
+ restore-keys: |
288
+ trivy-db-
289
+
290
+ - name: 🛡️ Trivy (Run & Report)
291
+ id: scan
292
+ run: |
293
+ C_NAME="trivy-${{ github.run_id }}"
294
+ docker rm -f $C_NAME 2>/dev/null || true
295
+ docker create --name $C_NAME -w /code aquasec/trivy:0.69.1 fs --config .gitea-config/.gitea/trivy.yaml --cache-dir /root/.cache --scanners vuln,misconfig,license --severity CRITICAL,HIGH --skip-dirs .git --exit-code 1 --no-progress .
296
+ docker cp . $C_NAME:/code
297
+ docker start -a $C_NAME > trivy.log 2>&1 || EXIT=$?
298
+
299
+ # Clean log from ANSI colors and limit size
300
+ sed -i 's/\x1b\[[0-9;]*m//g' trivy.log
301
+
302
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
303
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
304
+ cat trivy.log | tail -c 10000 >> $GITHUB_OUTPUT
305
+ echo '' >> $GITHUB_OUTPUT
306
+ echo 'EOF' >> $GITHUB_OUTPUT
307
+ fi
308
+ docker rm -f $C_NAME
309
+ exit ${EXIT:-0}
310
+
311
+ # 7.1 Composer Audit: PHP Security
312
+ composer-audit:
313
+ runs-on: "ubuntu-latest"
314
+ needs: [trivy, changes]
315
+ if: needs.changes.outputs.php == 'true'
316
+ outputs:
317
+ log: ${{ steps.scan.outputs.log }}
318
+ steps:
319
+ - name: Checkout code
320
+ uses: actions/checkout@v4
321
+ with:
322
+ token: ${{ secrets.GITHUB_TOKEN }}
323
+
324
+ - name: 🐘 Composer Audit (Run & Report)
325
+ id: scan
326
+ run: |
327
+ if [ -f composer.lock ]; then
328
+ C_NAME="composer-audit-${{ github.run_id }}"
329
+ docker rm -f $C_NAME 2>/dev/null || true
330
+ docker create --name $C_NAME -w /code composer:2 composer audit
331
+ docker cp . $C_NAME:/code
332
+ docker start -a $C_NAME > composer.log 2>&1 || EXIT=$?
333
+ sed -i 's/\x1b\[[0-9;]*m//g' composer.log
334
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
335
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
336
+ cat composer.log | tail -c 10000 >> $GITHUB_OUTPUT
337
+ echo '' >> $GITHUB_OUTPUT
338
+ echo 'EOF' >> $GITHUB_OUTPUT
339
+ fi
340
+ docker rm -f $C_NAME
341
+ exit ${EXIT:-0}
342
+ else
343
+ echo "No composer.lock found, skipping audit."
344
+ fi
345
+
346
+ # 8. Lint JS/TS (ESLint)
347
+ lint-js:
348
+ runs-on: "ubuntu-latest"
349
+ needs: [composer-audit, changes]
350
+ if: needs.changes.outputs.js == 'true'
351
+ outputs:
352
+ log: ${{ steps.lint.outputs.log }}
353
+ steps:
354
+ - uses: actions/checkout@v4
355
+ with:
356
+ token: ${{ secrets.GITHUB_TOKEN }}
357
+
358
+ - name: Lint JS/TS
359
+ id: lint
360
+ run: |
361
+ if [ -f package.json ]; then
362
+ C_NAME="js-lint-${{ github.run_id }}"
363
+ docker rm -f $C_NAME 2>/dev/null || true
364
+ # Create container
365
+ docker create --name $C_NAME -w /app node:22-alpine /bin/sh -c "if [ -f package-lock.json ]; then npm ci; else npm install; fi && if npm run | grep -q 'lint'; then npm run lint; else echo 'No lint script found'; fi"
366
+
367
+ # Copy code
368
+ docker cp . $C_NAME:/app
369
+
370
+ # Run
371
+ docker start -a $C_NAME > lint-js.log 2>&1 || EXIT=$?
372
+ sed -i 's/\x1b\[[0-9;]*m//g' lint-js.log
373
+
374
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
375
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
376
+ cat lint-js.log | tail -c 10000 >> $GITHUB_OUTPUT
377
+ echo '' >> $GITHUB_OUTPUT
378
+ echo 'EOF' >> $GITHUB_OUTPUT
379
+ fi
380
+ docker rm -f $C_NAME
381
+ exit ${EXIT:-0}
382
+ else
383
+ echo "No package.json, skipping"
384
+ fi
385
+
386
+ # 9. Lint PHP (PHP-CS-Fixer)
387
+ lint-php:
388
+ runs-on: "ubuntu-latest"
389
+ needs: [lint-js, changes]
390
+ if: needs.changes.outputs.php == 'true'
391
+ outputs:
392
+ log: ${{ steps.lint.outputs.log }}
393
+ steps:
394
+ - uses: actions/checkout@v4
395
+ with:
396
+ token: ${{ secrets.GITHUB_TOKEN }}
397
+
398
+ - name: Lint PHP
399
+ id: lint
400
+ run: |
401
+ if [ -f composer.json ]; then
402
+ C_NAME="php-lint-${{ github.run_id }}"
403
+ docker rm -f $C_NAME 2>/dev/null || true
404
+ # Create container
405
+ docker create --name $C_NAME -w /app composer:2 /bin/sh -c "composer install --no-progress --prefer-dist && if [ -f vendor/bin/php-cs-fixer ]; then vendor/bin/php-cs-fixer fix --dry-run --diff; else echo 'No php-cs-fixer found'; fi"
406
+
407
+ # Copy code
408
+ docker cp . $C_NAME:/app
409
+
410
+ # Run
411
+ docker start -a $C_NAME > lint-php.log 2>&1 || EXIT=$?
412
+ sed -i 's/\x1b\[[0-9;]*m//g' lint-php.log
413
+
414
+ if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then
415
+ echo 'log<<EOF' >> $GITHUB_OUTPUT
416
+ cat lint-php.log | tail -c 10000 >> $GITHUB_OUTPUT
417
+ echo '' >> $GITHUB_OUTPUT
418
+ echo 'EOF' >> $GITHUB_OUTPUT
419
+ fi
420
+ docker rm -f $C_NAME
421
+ exit ${EXIT:-0}
422
+ else
423
+ echo "No composer.json, skipping"
424
+ fi
425
+
426
+ # --- Notification & Summary ---
427
+ notify:
428
+ runs-on: "ubuntu-latest"
429
+ if: always() && !cancelled()
430
+ needs: [gitleaks, semgrep, hadolint, shellcheck, checkov-scan, trivy, composer-audit, lint-js, lint-php]
431
+ steps:
432
+ - name: Generate Summary Table
433
+ env:
434
+ LOG_GITLEAKS: ${{ needs.gitleaks.outputs.log }}
435
+ LOG_SEMGREP: ${{ needs.semgrep.outputs.log }}
436
+ LOG_HADOLINT: ${{ needs.hadolint.outputs.log }}
437
+ LOG_SHELLCHECK: ${{ needs.shellcheck.outputs.log }}
438
+ LOG_CHECKOV: ${{ needs.checkov-scan.outputs.log }}
439
+ LOG_TRIVY: ${{ needs.trivy.outputs.log }}
440
+ LOG_COMPOSER: ${{ needs.composer-audit.outputs.log }}
441
+ LOG_LINT_JS: ${{ needs.lint-js.outputs.log }}
442
+ LOG_LINT_PHP: ${{ needs.lint-php.outputs.log }}
443
+ run: |
444
+ SUMMARY_FILE="/tmp/security_summary.md"
445
+ DETAILS_FILE="/tmp/security_details.md"
446
+
447
+ echo "# 🔒 Security & Quality Report" > $SUMMARY_FILE
448
+ echo "" >> $SUMMARY_FILE
449
+ echo "| Check | Status |" >> $SUMMARY_FILE
450
+ echo "| :--- | :--- |" >> $SUMMARY_FILE
451
+
452
+ # Initialize details file
453
+ echo "" > $DETAILS_FILE
454
+ echo "### 🔍 Failure Details" >> $DETAILS_FILE
455
+ echo "" >> $DETAILS_FILE
456
+
457
+ clean_log() {
458
+ local log="$1"
459
+ log=$(echo "$log" | sed 's/\x1b\[[0-9;]*m//g')
460
+ echo "$log"
461
+ }
462
+
463
+ print_row() {
464
+ local job=$1
465
+ local status=$2
466
+ local log_var=$3
467
+ local log_content="${!log_var}"
468
+ local log=$(clean_log "$log_content")
469
+ local icon="❓"
470
+
471
+ if [[ "$status" == "success" ]]; then icon="✅ Success"; fi
472
+ if [[ "$status" == "failure" ]]; then
473
+ icon="❌ Failure"
474
+ echo "<details><summary><strong>$job</strong> Output</summary>" >> $DETAILS_FILE
475
+ echo "" >> $DETAILS_FILE
476
+ echo "\`\`\`" >> $DETAILS_FILE
477
+ echo "$log" >> $DETAILS_FILE
478
+ echo "\`\`\`" >> $DETAILS_FILE
479
+ echo "" >> $DETAILS_FILE
480
+ echo "</details>" >> $DETAILS_FILE
481
+ echo "" >> $DETAILS_FILE
482
+ fi
483
+ if [[ "$status" == "skipped" ]]; then icon="⏭️ Skipped"; fi
484
+
485
+ echo "| **$job** | $icon |" >> $SUMMARY_FILE
486
+ }
487
+
488
+ print_row "Gitleaks" "${{ needs.gitleaks.result }}" "LOG_GITLEAKS"
489
+ print_row "Semgrep" "${{ needs.semgrep.result }}" "LOG_SEMGREP"
490
+ print_row "Hadolint" "${{ needs.hadolint.result }}" "LOG_HADOLINT"
491
+ print_row "ShellCheck" "${{ needs.shellcheck.result }}" "LOG_SHELLCHECK"
492
+ print_row "Checkov" "${{ needs.checkov-scan.result }}" "LOG_CHECKOV"
493
+ print_row "Trivy" "${{ needs.trivy.result }}" "LOG_TRIVY"
494
+ print_row "Composer" "${{ needs.composer-audit.result }}" "LOG_COMPOSER"
495
+ print_row "Lint JS" "${{ needs.lint-js.result }}" "LOG_LINT_JS"
496
+ print_row "Lint PHP" "${{ needs.lint-php.result }}" "LOG_LINT_PHP"
497
+
498
+ cat $DETAILS_FILE >> $SUMMARY_FILE
499
+ cat $SUMMARY_FILE >> $GITHUB_STEP_SUMMARY
500
+
501
+ - name: Post Comment to PR
502
+ if: always() && github.event_name == 'pull_request'
503
+ env:
504
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
505
+ API_URL: ${{ github.api_url }}
506
+ REPO: ${{ github.repository }}
507
+ PR_NUMBER: ${{ github.event.number }}
508
+ S_GITLEAKS: ${{ needs.gitleaks.result }}
509
+ S_SEMGREP: ${{ needs.semgrep.result }}
510
+ S_HADOLINT: ${{ needs.hadolint.result }}
511
+ S_SHELLCHECK: ${{ needs.shellcheck.result }}
512
+ S_CHECKOV: ${{ needs.checkov-scan.result }}
513
+ S_TRIVY: ${{ needs.trivy.result }}
514
+ S_COMPOSER: ${{ needs.composer-audit.result }}
515
+ S_LINT_JS: ${{ needs.lint-js.result }}
516
+ S_LINT_PHP: ${{ needs.lint-php.result }}
517
+ run: |
518
+ if [ -z "$PR_NUMBER" ]; then exit 0; fi
519
+
520
+ if [[ "$S_GITLEAKS" == "failure" ]] || [[ "$S_SEMGREP" == "failure" ]] || [[ "$S_HADOLINT" == "failure" ]] || [[ "$S_SHELLCHECK" == "failure" ]] || [[ "$S_CHECKOV" == "failure" ]] || [[ "$S_TRIVY" == "failure" ]] || [[ "$S_COMPOSER" == "failure" ]] || [[ "$S_LINT_JS" == "failure" ]] || [[ "$S_LINT_PHP" == "failure" ]]; then
521
+ TITLE="### 🛡️ Checks Failed ❌"
522
+ else
523
+ TITLE="### 🛡️ Checks Passed ✅"
524
+ fi
525
+
526
+ echo "$TITLE" > /tmp/comment_body.md
527
+ echo "" >> /tmp/comment_body.md
528
+ if [ -f "/tmp/security_summary.md" ]; then
529
+ cat /tmp/security_summary.md >> /tmp/comment_body.md
530
+ fi
531
+
532
+ python3 -c 'import json, sys; print(json.dumps({"body": sys.stdin.read()}))' < /tmp/comment_body.md > /tmp/comment.json
533
+
534
+ curl -s -X POST "$API_URL/repos/$REPO/issues/$PR_NUMBER/comments" \
535
+ -H "Authorization: token $GITHUB_TOKEN" \
536
+ -H "Content-Type: application/json" \
537
+ -d @/tmp/comment.json
538
+
539
+ - name: Send Telegram Notification
540
+ if: always()
541
+ env:
542
+ TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
543
+ TG_TO: ${{ secrets.TELEGRAM_TO }}
544
+ TG_THREAD_ID: ${{ secrets.TELEGRAM_THREAD_ID }}
545
+ COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
546
+ REPO: ${{ github.repository }}
547
+ BRANCH: ${{ github.ref_name }}
548
+ ACTOR: ${{ github.actor }}
549
+ SERVER_URL: https://git.boringstudio.by
550
+ RUN_ID: ${{ github.run_id }}
551
+ SHA: ${{ github.sha }}
552
+ # Statuses
553
+ S_GITLEAKS: ${{ needs.gitleaks.result }}
554
+ S_SEMGREP: ${{ needs.semgrep.result }}
555
+ S_HADOLINT: ${{ needs.hadolint.result }}
556
+ S_SHELLCHECK: ${{ needs.shellcheck.result }}
557
+ S_CHECKOV: ${{ needs.checkov-scan.result }}
558
+ S_TRIVY: ${{ needs.trivy.result }}
559
+ S_COMPOSER: ${{ needs.composer-audit.result }}
560
+ S_LINT_JS: ${{ needs.lint-js.result }}
561
+ S_LINT_PHP: ${{ needs.lint-php.result }}
562
+ run: |
563
+ # Determine Overall Status
564
+ if [[ "$S_GITLEAKS" == "failure" ]] || [[ "$S_SEMGREP" == "failure" ]] || [[ "$S_HADOLINT" == "failure" ]] || [[ "$S_SHELLCHECK" == "failure" ]] || [[ "$S_CHECKOV" == "failure" ]] || [[ "$S_TRIVY" == "failure" ]] || [[ "$S_COMPOSER" == "failure" ]] || [[ "$S_LINT_JS" == "failure" ]] || [[ "$S_LINT_PHP" == "failure" ]]; then
565
+ STATUS="failure"
566
+ ICON="❌"
567
+ else
568
+ STATUS="success"
569
+ ICON="✅"
570
+ fi
571
+
572
+ # Skip Telegram on Successful PRs
573
+ if [[ "$STATUS" == "success" ]] && [[ "${{ github.event_name }}" == "pull_request" ]]; then
574
+ echo "✅ PR Success. Skipping Telegram notification."
575
+ exit 0
576
+ fi
577
+
578
+ COMMIT_MSG_CLEAN=$(printf "%s" "$COMMIT_MESSAGE" | head -n 1 | sed 's/"/\\"/g')
579
+
580
+ # Build Detail List
581
+ DETAILS=""
582
+ add_status() {
583
+ local name=$1
584
+ local res=$2
585
+ local i="✅"
586
+ if [[ "$res" == "failure" ]]; then i="❌"; fi
587
+ if [[ "$res" == "skipped" ]]; then i="⏭️"; fi
588
+ DETAILS="${DETAILS}${i} ${name}\n"
589
+ }
590
+
591
+ add_status "Gitleaks" "$S_GITLEAKS"
592
+ add_status "Semgrep" "$S_SEMGREP"
593
+ add_status "Hadolint" "$S_HADOLINT"
594
+ add_status "ShellCheck" "$S_SHELLCHECK"
595
+ add_status "Checkov" "$S_CHECKOV"
596
+ add_status "Trivy" "$S_TRIVY"
597
+ add_status "Composer" "$S_COMPOSER"
598
+ add_status "Lint JS" "$S_LINT_JS"
599
+ add_status "Lint PHP" "$S_LINT_PHP"
600
+
601
+ # Escape newlines for JSON
602
+ DETAILS_JSON=$(echo -e "$DETAILS" | sed ':a;N;$!ba;s/\n/\\n/g')
603
+
604
+ curl -s -X POST "https://api.telegram.org/bot$TG_TOKEN/sendMessage" \
605
+ -H 'Content-Type: application/json' \
606
+ -d "{
607
+ \"chat_id\": \"$TG_TO\",
608
+ \"message_thread_id\": \"$TG_THREAD_ID\",
609
+ \"parse_mode\": \"HTML\",
610
+ \"text\": \"🔒 <b>Security & Quality: $ICON</b>\n\n📂 <b>Repo:</b> <a href=\\\"$SERVER_URL/$REPO\\\">$REPO</a>\n🌿 <b>Branch:</b> <code>$BRANCH</code>\n👤 <b>User:</b> $ACTOR\n📝 <b>Commit:</b> <i>$COMMIT_MSG_CLEAN</i>\n\n<b>Details:</b>\n$DETAILS_JSON\n\n🔗 <a href=\\\"$SERVER_URL/$REPO/commit/$SHA\\\">View Commit</a> | <a href=\\\"$SERVER_URL/$REPO/actions\\\">View Actions</a>\"
611
+ }"
@@ -0,0 +1,22 @@
1
+ # See https://pre-commit.com for more information
2
+ # See https://pre-commit.com/hooks.html for more hooks
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v4.5.0
6
+ hooks:
7
+ - id: trailing-whitespace
8
+ - id: end-of-file-fixer
9
+ - id: check-yaml
10
+ - id: check-added-large-files
11
+ - id: check-merge-conflict
12
+
13
+ - repo: https://github.com/gitleaks/gitleaks
14
+ rev: v8.18.2
15
+ hooks:
16
+ - id: gitleaks
17
+
18
+ - repo: https://github.com/editorconfig-checker/editorconfig-checker.python
19
+ rev: 2.7.3
20
+ hooks:
21
+ - id: editorconfig-checker
22
+ alias: ec
package/CHANGELOG.md CHANGED
@@ -2,77 +2,127 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [1.9.0](https://github.com/boringstudio-org/mcp-gitea/compare/v1.8.0...v1.9.0) (2026-03-13)
6
+
7
+
8
+ ### Features
9
+
10
+ * add husky and gitleaks, ignore .idea ([b706acc](https://github.com/boringstudio-org/mcp-gitea/commit/b706accd83998bdce9082040abcff54b72f3fb56))
11
+ * add project files (v1.4.0) ([01ae6c1](https://github.com/boringstudio-org/mcp-gitea/commit/01ae6c10b4f5ec17d606db69da0d9d9cd0ea82ec))
12
+ * **ci:** pass secrets explicitly in security workflow ([0d9604f](https://github.com/boringstudio-org/mcp-gitea/commit/0d9604f0b4cebc1180e0b971abb898424521b928))
13
+ * enhance security and optimization ([72d3a8a](https://github.com/boringstudio-org/mcp-gitea/commit/72d3a8ac8b3c590025e43f00578a167906ee2e0f))
14
+ * update readme with security details ([650ffde](https://github.com/boringstudio-org/mcp-gitea/commit/650ffde4e25c0b7b472b7a9b20c5bd4da695e0e2))
15
+ * update security, dependencies and CI workflow (v1.8.0) ([#34](https://github.com/boringstudio-org/mcp-gitea/issues/34)) ([faf4dba](https://github.com/boringstudio-org/mcp-gitea/commit/faf4dba5d0373830d3776017b77467cad6941672))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **ci:** add .versionrc to skip ci on release commits ([4a8856b](https://github.com/boringstudio-org/mcp-gitea/commit/4a8856bc93215f98aa7eb0637a449601b1c96bd9))
21
+ * **ci:** checkout main branch before release ([d85bd5c](https://github.com/boringstudio-org/mcp-gitea/commit/d85bd5c57982d25d4cc2145f41ae21c75e91f97a))
22
+ * **ci:** use admin email for release workflow ([9fb8e1d](https://github.com/boringstudio-org/mcp-gitea/commit/9fb8e1d14a2ca30bb4e81d6587c1aed6f4541d03))
23
+ * **ci:** use correct bot email for release workflow ([c4899e4](https://github.com/boringstudio-org/mcp-gitea/commit/c4899e46e32e621273ebdde9f783d3ff29f9a251))
24
+ * **deps:** pin dependencies ([641be6b](https://github.com/boringstudio-org/mcp-gitea/commit/641be6b051289d3f6023a6fa2adfd58247052c9a))
25
+ * **deps:** resolve merge conflict, update sdk to 1.26.0 and axios to 1.13.5 ([bf5dd0a](https://github.com/boringstudio-org/mcp-gitea/commit/bf5dd0afdc01fa2e71e1856286ccd2ae52b56080))
26
+ * **deps:** update @modelcontextprotocol/sdk to 1.26.0 to fix CVE-2026-25536 ([57480cb](https://github.com/boringstudio-org/mcp-gitea/commit/57480cbfbb355b71caa0d00cc634ecc6f655fb30))
27
+ * **deps:** update dependency @modelcontextprotocol/sdk to v1.27.0 ([a743a42](https://github.com/boringstudio-org/mcp-gitea/commit/a743a42fc2eee5d5180bb8189d26c01c6cffdf17))
28
+ * **deps:** update dependency @modelcontextprotocol/sdk to v1.27.1 ([f8a6d52](https://github.com/boringstudio-org/mcp-gitea/commit/f8a6d5205662370bb9fec1bfb17da3573fb11164))
29
+ * **deps:** update dependency axios to v1.13.5 ([3236b60](https://github.com/boringstudio-org/mcp-gitea/commit/3236b607f1521ec2b5e367e183eb2f5ed2afa4cf))
30
+ * **deps:** update dependency axios to v1.13.6 ([02d21a7](https://github.com/boringstudio-org/mcp-gitea/commit/02d21a7d1b791fe35b6fbe7feb87805274882528))
31
+ * **deps:** update dependency dotenv to v17.3.1 ([d6b40ae](https://github.com/boringstudio-org/mcp-gitea/commit/d6b40ae2c342bdb96505da6ac3814f728538b7e9))
32
+ * resolve merge conflicts in CHANGELOG.md ([01db96f](https://github.com/boringstudio-org/mcp-gitea/commit/01db96f4fb1fb8c6d2baa4e05dbdc921d9644658))
33
+ * resolve semgrep security findings ([5615cfa](https://github.com/boringstudio-org/mcp-gitea/commit/5615cfa9db3eb65cc95bc34338891f5dead679cc))
34
+ * resolve semgrep security findings ([05b45a7](https://github.com/boringstudio-org/mcp-gitea/commit/05b45a72da017c122a8e08e2c38ce56c2654dbab))
35
+ * **security:** override @isaacs/brace-expansion to v5.0.1 to resolve CVE-2026-25547 ([aa220c1](https://github.com/boringstudio-org/mcp-gitea/commit/aa220c14ad9e2d31a6da25677d0d996347305f32))
36
+
37
+ ## [1.8.0](https://github.com/boringstudio-org/mcp-gitea/compare/v1.7.0...v1.8.0) (2026-01-17)
38
+
5
39
  ### [1.7.1](https://git.boringstudio.by/BoringStudio/mcp-gitea/compare/v1.7.0...v1.7.1) (2026-01-15)
6
40
 
7
41
  ## [1.7.0](https://git.boringstudio.by/BoringStudio/mcp-gitea/compare/v1.6.1...v1.7.0) (2026-01-15)
8
42
 
43
+ ### Features
44
+
45
+ * add project files (v1.4.0) ([01ae6c1](https://github.com/boringstudio-org/mcp-gitea/commit/01ae6c10b4f5ec17d606db69da0d9d9cd0ea82ec))
46
+ * enhance security and optimization ([72d3a8a](https://github.com/boringstudio-org/mcp-gitea/commit/72d3a8ac8b3c590025e43f00578a167906ee2e0f))
47
+ * update readme with security details ([650ffde](https://github.com/boringstudio-org/mcp-gitea/commit/650ffde4e25c0b7b472b7a9b20c5bd4da695e0e2))
48
+
49
+
50
+ ### Bug Fixes
51
+
52
+ * **ci:** add .versionrc to skip ci on release commits ([4a8856b](https://github.com/boringstudio-org/mcp-gitea/commit/4a8856bc93215f98aa7eb0637a449601b1c96bd9))
53
+ * **ci:** checkout main branch before release ([d85bd5c](https://github.com/boringstudio-org/mcp-gitea/commit/d85bd5c57982d25d4cc2145f41ae21c75e91f97a))
54
+ * **ci:** use admin email for release workflow ([9fb8e1d](https://github.com/boringstudio-org/mcp-gitea/commit/9fb8e1d14a2ca30bb4e81d6587c1aed6f4541d03))
55
+ * **ci:** use correct bot email for release workflow ([c4899e4](https://github.com/boringstudio-org/mcp-gitea/commit/c4899e46e32e621273ebdde9f783d3ff29f9a251))
56
+
57
+ ## [1.7.0](https://github.com/boringstudio-org/mcp-gitea/compare/v1.6.1...v1.7.0) (2026-01-15)
58
+
9
59
 
10
60
  ### Features
11
61
 
12
- * update readme with security details ([#7](https://git.boringstudio.by/BoringStudio/mcp-gitea/issues/7)) ([9c719bb](https://git.boringstudio.by/BoringStudio/mcp-gitea/commit/9c719bbf6f4e46bcba98f3656f899c9e11fd1e5e))
62
+ * update readme with security details ([#7](https://github.com/boringstudio-org/mcp-gitea/issues/7)) ([9c719bb](https://github.com/boringstudio-org/mcp-gitea/commit/9c719bbf6f4e46bcba98f3656f899c9e11fd1e5e))
13
63
 
14
- ### [1.6.1](https://git.boringstudio.by/BoringStudio/mcp-gitea/compare/v1.6.0...v1.6.1) (2026-01-15)
64
+ ### [1.6.1](https://github.com/boringstudio-org/mcp-gitea/compare/v1.6.0...v1.6.1) (2026-01-15)
15
65
 
16
- ## [1.6.0](https://git.boringstudio.by/BoringStudio/mcp-gitea/compare/v1.4.1...v1.6.0) (2026-01-15)
66
+ ## [1.6.0](https://github.com/boringstudio-org/mcp-gitea/compare/v1.4.1...v1.6.0) (2026-01-15)
17
67
 
18
68
 
19
69
  ### Features
20
70
 
21
- * enhance security and optimization ([#5](https://git.boringstudio.by/BoringStudio/mcp-gitea/issues/5)) ([f9f7055](https://git.boringstudio.by/BoringStudio/mcp-gitea/commit/f9f70556240482149ac245357f23f1160e873e5c))
71
+ * enhance security and optimization ([#5](https://github.com/boringstudio-org/mcp-gitea/issues/5)) ([f9f7055](https://github.com/boringstudio-org/mcp-gitea/commit/f9f70556240482149ac245357f23f1160e873e5c))
22
72
 
23
73
  ### 1.4.1 (2026-01-14)
24
74
 
25
- ### [1.3.6](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.5...v1.3.6) (2026-01-14)
75
+ ### [1.3.6](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.5...v1.3.6) (2026-01-14)
26
76
 
27
- ### [1.3.5](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.4...v1.3.5) (2026-01-14)
77
+ ### [1.3.5](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.4...v1.3.5) (2026-01-14)
28
78
 
29
79
 
30
80
  ### Bug Fixes
31
81
 
32
- * Update start script to use global package and load env ([#20](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/20)) ([c4598fc](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/c4598fce2bbfcd9acc48599fe0eddde013ecedb5))
82
+ * Update start script to use global package and load env ([#20](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/20)) ([c4598fc](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/c4598fce2bbfcd9acc48599fe0eddde013ecedb5))
33
83
 
34
- ### [1.3.4](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.3...v1.3.4) (2026-01-14)
84
+ ### [1.3.4](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.3...v1.3.4) (2026-01-14)
35
85
 
36
86
 
37
87
  ### Features
38
88
 
39
- * Native Node.js Google Search implementation ([#19](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/19)) ([555f44a](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/555f44a9bd9017d2cd01351efe19b5b2c766b442))
89
+ * Native Node.js Google Search implementation ([#19](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/19)) ([555f44a](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/555f44a9bd9017d2cd01351efe19b5b2c766b442))
40
90
 
41
- ### [1.3.3](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.2...v1.3.3) (2026-01-14)
91
+ ### [1.3.3](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.2...v1.3.3) (2026-01-14)
42
92
 
43
93
 
44
94
  ### Bug Fixes
45
95
 
46
- * Silence npx output, map Google ID, add start script and update docs ([#18](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/18)) ([7c36bdc](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/7c36bdcedd5c29281a1562a7a801c3d0ac6d3256))
96
+ * Silence npx output, map Google ID, add start script and update docs ([#18](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/18)) ([7c36bdc](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/7c36bdcedd5c29281a1562a7a801c3d0ac6d3256))
47
97
 
48
- ### [1.3.2](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.1...v1.3.2) (2026-01-14)
98
+ ### [1.3.2](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.1...v1.3.2) (2026-01-14)
49
99
 
50
100
 
51
101
  ### Bug Fixes
52
102
 
53
- * Add ~/.local/bin to PATH for uvx discovery ([#16](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/16)) ([b2a25d5](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/b2a25d5fa5ec6d5d9fface87d48eb431ff9fd175))
103
+ * Add ~/.local/bin to PATH for uvx discovery ([#16](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/16)) ([b2a25d5](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/b2a25d5fa5ec6d5d9fface87d48eb431ff9fd175))
54
104
 
55
- ### [1.3.1](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.3.0...v1.3.1) (2026-01-14)
105
+ ### [1.3.1](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.3.0...v1.3.1) (2026-01-14)
56
106
 
57
107
 
58
108
  ### Bug Fixes
59
109
 
60
- * Remove hardcoded env from npm config and update docs ([9842c48](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/9842c48e07e91a0d5b79d547782aa0aa9b6d9390))
110
+ * Remove hardcoded env from npm config and update docs ([9842c48](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/9842c48e07e91a0d5b79d547782aa0aa9b6d9390))
61
111
 
62
- ## [1.3.0](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/compare/v1.2.0...v1.3.0) (2026-01-13)
112
+ ## [1.3.0](https://github.com/boringstudio-org/mcp-gitea-proxy/compare/v1.2.0...v1.3.0) (2026-01-13)
63
113
 
64
114
  ## 1.2.0 (2026-01-13)
65
115
 
66
116
 
67
117
  ### Features
68
118
 
69
- * add create_pull_request and list_branches tools (Closes [#3](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/3)) ([465d4ed](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/465d4ed1738cf7e54d2b67b7a8c5f2df70194cfe))
70
- * add list_labels and update_issue with labels support (Closes [#2](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/issues/2)) ([9006385](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/9006385ce82cd5adc5f7af9bdbf5e28c89789816))
71
- * add memory schema docs and update project structure ([841b0d6](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/841b0d6075c9e9b501a7d76a7cfa10a1f228a2bb))
72
- * add secure shell execution and full Gitea integration ([d22d48c](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/d22d48cb99de046b560313995b08d1c67955fb41))
73
- * upgrade to v1.4.0 with Resources and Prompts ([1510e9e](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/1510e9e7e1b3d682c011a7fdc56ae2b26435c086))
119
+ * add create_pull_request and list_branches tools (Closes [#3](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/3)) ([465d4ed](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/465d4ed1738cf7e54d2b67b7a8c5f2df70194cfe))
120
+ * add list_labels and update_issue with labels support (Closes [#2](https://github.com/boringstudio-org/mcp-gitea-proxy/issues/2)) ([9006385](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/9006385ce82cd5adc5f7af9bdbf5e28c89789816))
121
+ * add memory schema docs and update project structure ([841b0d6](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/841b0d6075c9e9b501a7d76a7cfa10a1f228a2bb))
122
+ * add secure shell execution and full Gitea integration ([d22d48c](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/d22d48cb99de046b560313995b08d1c67955fb41))
123
+ * upgrade to v1.4.0 with Resources and Prompts ([1510e9e](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/1510e9e7e1b3d682c011a7fdc56ae2b26435c086))
74
124
 
75
125
 
76
126
  ### Bug Fixes
77
127
 
78
- * Add fallback for uvx path ([dba4e21](https://git.boringstudio.by/BoringStudio/mcp-gitea-proxy/commit/dba4e213790c91a8d031c37cac9a0eaf8724664a))
128
+ * Add fallback for uvx path ([dba4e21](https://github.com/boringstudio-org/mcp-gitea-proxy/commit/dba4e213790c91a8d031c37cac9a0eaf8724664a))
package/README.md CHANGED
@@ -29,9 +29,14 @@ npm install @boringstudio_org/gitea-mcp
29
29
  ```bash
30
30
  # Configure environment variables
31
31
  export GITEA_TOKEN=your_token
32
- # Optional: Defaults to https://git.boringstudio.by/api/v1
32
+ # Optional: Defaults to https://git.your-instance.com/api/v1
33
33
  export GITEA_API_URL=https://git.your-instance.com/api/v1
34
34
 
35
+ # Cloudflare Access (Optional)
36
+ # If your Gitea instance is behind Cloudflare Zero Trust
37
+ export CF_ID=your_cf_client_id
38
+ export CF_SECRET=your_cf_client_secret
39
+
35
40
  # Run
36
41
  npx @boringstudio_org/gitea-mcp
37
42
  ```
@@ -42,7 +47,11 @@ npx @boringstudio_org/gitea-mcp
42
47
  npm install
43
48
 
44
49
  # Configure .env
45
- echo "Gitea_TOKEN=..." > .env
50
+ echo "GITEA_TOKEN=..." > .env
51
+ echo "GITEA_API_URL=..." >> .env
52
+ # Optional: Cloudflare Access
53
+ echo "CF_ID=..." >> .env
54
+ echo "CF_SECRET=..." >> .env
46
55
 
47
56
  # Run
48
57
  node index.js
package/RELEASE.md ADDED
@@ -0,0 +1,48 @@
1
+ # 🚀 Release Process
2
+
3
+ Releases for `@boringstudio_org/gitea-mcp` are automated via Gitea Actions.
4
+
5
+ ## 🛠 Prerequisites
6
+
7
+ * **NPM Token**: `NPM_TOKEN` must be configured in repository secrets for publishing.
8
+ * **Git Token**: `GITEA_TOKEN` or `RENOVATE_TOKEN` with write permissions for automated tagging.
9
+
10
+ ## 📋 Steps to Release
11
+
12
+ ### 1. Prepare Release (on `dev` branch)
13
+ Run the release script locally to bump the version and generate the changelog.
14
+ **Important**: Use `--no-tag` to let the CI handle the official tagging on the `main` branch.
15
+
16
+ ```bash
17
+ # For a bug fix (patch): 1.8.0 -> 1.8.1
18
+ npm run release -- --release-as patch --no-tag
19
+
20
+ # For a new feature (minor): 1.8.0 -> 1.9.0
21
+ npm run release -- --release-as minor --no-tag
22
+ ```
23
+
24
+ This command will:
25
+ * Update `version` in `package.json`.
26
+ * Append new changes to `CHANGELOG.md`.
27
+ * Create a "chore(release): X.X.X" commit.
28
+
29
+ ### 2. Push to Development
30
+ ```bash
31
+ git push origin dev
32
+ ```
33
+
34
+ ### 3. Merge to Main
35
+ 1. Open a **Pull Request** from `dev` to `main` in Gitea.
36
+ 2. Complete the code review.
37
+ 3. Merge the PR.
38
+
39
+ ### 4. Automation (CI)
40
+ Once the release commit is merged into `main`, the Gitea Action will:
41
+ * Detect the version bump.
42
+ * **Publish** the package to the NPM registry.
43
+ * **Create & Push** the official git tag (e.g., `v1.9.0`) to the repository.
44
+
45
+ ## 🔍 Troubleshooting
46
+
47
+ * **Release not triggered?** Ensure the `chore(release)` commit is present on the `main` branch and the version is unique.
48
+ * **NPM Publish failed?** Verify the `NPM_TOKEN` has not expired and has "Automation" permissions.
package/index.js CHANGED
@@ -7,6 +7,10 @@ import dotenv from "dotenv";
7
7
  import path from "path";
8
8
  import { fileURLToPath } from 'url';
9
9
  import { spawn } from "child_process";
10
+ import { createRequire } from "module";
11
+
12
+ const require = createRequire(import.meta.url);
13
+ const pkg = require("./package.json");
10
14
 
11
15
  // Load .env from the current working directory
12
16
  dotenv.config({ path: path.join(process.cwd(), ".env"), quiet: true });
@@ -14,11 +18,11 @@ dotenv.config({ path: path.join(process.cwd(), ".env"), quiet: true });
14
18
  export async function runGiteaServer() {
15
19
  const server = new McpServer({
16
20
  name: "gitea-proxy-agent",
17
- version: "1.5.0",
21
+ version: pkg.version,
18
22
  });
19
23
 
20
24
  const GITEA_TOKEN = process.env.GITEA_TOKEN;
21
- const BASE_URL = process.env.GITEA_API_URL || "https://git.boringstudio.by/api/v1";
25
+ const BASE_URL = process.env.GITEA_API_URL;
22
26
 
23
27
  if (!GITEA_TOKEN) {
24
28
  console.error("❌ Error: GITEA_TOKEN not found.");
@@ -48,7 +52,7 @@ export async function runGiteaServer() {
48
52
  const config = { method, url: endpoint };
49
53
  if (data) config.data = data;
50
54
  if (params) config.params = params;
51
-
55
+
52
56
  const response = await api(config);
53
57
  return response.data;
54
58
  } catch (error) {
@@ -136,9 +140,11 @@ export async function runGiteaServer() {
136
140
  // --- TOOLS ---
137
141
 
138
142
  // Security: Allowed paths for run_safe_shell
143
+ // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
139
144
  const ALLOWED_PATHS = (process.env.MCP_ALLOWED_PATHS || process.cwd()).split(',').map(p => path.resolve(p.trim()));
140
145
 
141
146
  function isPathAllowed(targetPath) {
147
+ // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
142
148
  const resolved = path.resolve(targetPath);
143
149
  return ALLOWED_PATHS.some(allowed => resolved.startsWith(allowed));
144
150
  }
@@ -182,6 +188,7 @@ export async function runGiteaServer() {
182
188
  }
183
189
 
184
190
  return new Promise((resolve) => {
191
+ // nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
185
192
  const child = spawn(command, args, {
186
193
  cwd: cwd,
187
194
  env: process.env,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boringstudio_org/gitea-mcp",
3
- "version": "1.7.1",
3
+ "version": "1.9.0",
4
4
  "description": "A Gitea MCP Server for interacting with repositories, issues, and more.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -9,18 +9,23 @@
9
9
  },
10
10
  "scripts": {
11
11
  "start": "node index.js",
12
- "release": "standard-version"
12
+ "release": "standard-version",
13
+ "test": "echo \"No tests yet\" && exit 0",
14
+ "scan:secrets": "docker run --rm -v \"$(pwd):/path\" zricethezav/gitleaks:latest detect --source=\"/path\" -v"
13
15
  },
14
16
  "dependencies": {
15
- "@modelcontextprotocol/sdk": "^1.25.2",
16
- "axios": "^1.7.9",
17
- "dotenv": "^17.2.3",
18
- "zod": "^3.24.1"
17
+ "@modelcontextprotocol/sdk": "1.27.1",
18
+ "axios": "1.13.6",
19
+ "dotenv": "17.3.1",
20
+ "zod": "3.25.76"
21
+ },
22
+ "overrides": {
23
+ "@isaacs/brace-expansion": "5.0.1"
19
24
  },
20
25
  "license": "MIT",
21
26
  "repository": {
22
27
  "type": "git",
23
- "url": "https://git.boringstudio.by/BoringStudio/mcp-gitea.git"
28
+ "url": "https://github.com/boringstudio-org/mcp-gitea.git"
24
29
  },
25
30
  "keywords": [
26
31
  "mcp",
@@ -33,6 +38,6 @@
33
38
  "access": "public"
34
39
  },
35
40
  "devDependencies": {
36
- "standard-version": "^9.5.0"
41
+ "standard-version": "9.5.0"
37
42
  }
38
43
  }
package/renovate.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "extends": [
3
+ "config:recommended",
4
+ ":disableMajorUpdates"
5
+ ],
6
+ "prConcurrentLimit": 2,
7
+ "baseBranchPatterns": [
8
+ "dev"
9
+ ],
10
+ "useBaseBranchConfig": "merge",
11
+ "labels": [
12
+ "renovate"
13
+ ],
14
+ "rebaseWhen": "conflicted",
15
+ "rangeStrategy": "pin",
16
+ "packageRules": [
17
+ {
18
+ "matchDatasources": [
19
+ "docker",
20
+ "github-tags"
21
+ ],
22
+ "matchUpdateTypes": [
23
+ "minor",
24
+ "patch",
25
+ "pin",
26
+ "digest"
27
+ ],
28
+ "groupName": "CI tools updates"
29
+ }
30
+ ]
31
+ }