Skip to content

feat(node): Surge 导出透传 hysteria2 端口跳跃(port-hopping) #166

feat(node): Surge 导出透传 hysteria2 端口跳跃(port-hopping)

feat(node): Surge 导出透传 hysteria2 端口跳跃(port-hopping) #166

Workflow file for this run

name: PR Checks
on:
pull_request:
types:
- opened
- reopened
- ready_for_review
paths-ignore:
# 文档文件(不包括 skill-sublinkpro,它会被嵌入到二进制文件中)
- '*.md'
- 'docs/**'
# AI 代理配置和私有文档
- '.agents/**'
- '.claude/**'
- '.codex/**'
- 'AGENTS.md'
- 'CLAUDE.md'
- 'GEMINI.md'
- 'CONTRIBUTING.md'
# 编辑器/IDE 配置
- '.vscode/**'
- '.idea/**'
- '.editorconfig'
# Git 配置
- '.gitignore'
- '.gitattributes'
# 许可证文件
- 'LICENSE'
- 'COPYING'
issue_comment:
types:
- created
permissions:
contents: read
issues: write
pull-requests: read
jobs:
prepare-pr-check:
name: Prepare PR Check
if: github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request)
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.prepare.outputs.should_run }}
authorized: ${{ steps.prepare.outputs.authorized }}
checkout_repository: ${{ steps.prepare.outputs.checkout_repository }}
checkout_ref: ${{ steps.prepare.outputs.checkout_ref }}
pr_number: ${{ steps.prepare.outputs.pr_number }}
steps:
- name: Resolve PR context
id: prepare
env:
GH_TOKEN: ${{ github.token }}
EVENT_NAME: ${{ github.event_name }}
REPOSITORY: ${{ github.repository }}
ACTOR: ${{ github.actor }}
COMMENT_BODY: ${{ github.event.comment.body }}
COMMENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
COMMENT_IS_PR: ${{ github.event.issue.pull_request && 'true' || 'false' }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "authorized=false" >> "$GITHUB_OUTPUT"
if [ "$EVENT_NAME" = "pull_request" ]; then
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "authorized=true" >> "$GITHUB_OUTPUT"
echo "checkout_repository=$PR_HEAD_REPOSITORY" >> "$GITHUB_OUTPUT"
echo "checkout_ref=$PR_HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "$EVENT_NAME" != "issue_comment" ] || [ "$COMMENT_IS_PR" != "true" ]; then
exit 0
fi
command="$(printf '%s' "$COMMENT_BODY" | tr -d '\r' | head -n 1)"
if [ "$command" != "/recheck" ]; then
exit 0
fi
pr_author="$(gh api "repos/$REPOSITORY/pulls/$COMMENT_ISSUE_NUMBER" --jq '.user.login')"
checkout_repository="$(gh api "repos/$REPOSITORY/pulls/$COMMENT_ISSUE_NUMBER" --jq '.head.repo.full_name')"
checkout_ref="$(gh api "repos/$REPOSITORY/pulls/$COMMENT_ISSUE_NUMBER" --jq '.head.sha')"
actor_permission="$(gh api "repos/$REPOSITORY/collaborators/$ACTOR/permission" --jq '.permission' 2>/dev/null || echo "none")"
authorized=false
if [ "$ACTOR" = "$pr_author" ]; then
authorized=true
fi
if [ "$actor_permission" = "admin" ]; then
authorized=true
fi
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "authorized=$authorized" >> "$GITHUB_OUTPUT"
echo "checkout_repository=$checkout_repository" >> "$GITHUB_OUTPUT"
echo "checkout_ref=$checkout_ref" >> "$GITHUB_OUTPUT"
echo "pr_number=$COMMENT_ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
- name: Trigger summary
if: always()
run: |
echo "## PR Check Trigger" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "- Event: ${{ github.event_name }}" >> "$GITHUB_STEP_SUMMARY"
echo "- PR: #${{ steps.prepare.outputs.pr_number || github.event.issue.number || github.event.pull_request.number }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Should run: ${{ steps.prepare.outputs.should_run }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Authorized: ${{ steps.prepare.outputs.authorized }}" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "Comment-triggered reruns require the PR author or a repository admin to comment \`/recheck\`." >> "$GITHUB_STEP_SUMMARY"
backend-checks:
name: Backend Checks
needs: prepare-pr-check
if: needs.prepare-pr-check.outputs.should_run == 'true' && needs.prepare-pr-check.outputs.authorized == 'true'
runs-on: ubuntu-latest
outputs:
golangci: ${{ steps.backend-summary.outputs.golangci }}
gotest: ${{ steps.backend-summary.outputs.gotest }}
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
repository: ${{ needs.prepare-pr-check.outputs.checkout_repository }}
ref: ${{ needs.prepare-pr-check.outputs.checkout_ref }}
fetch-depth: 1
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.26.4'
cache: true
cache-dependency-path: go.sum
- name: Download Go modules
run: go mod download
- name: Run golangci-lint
id: golangci
continue-on-error: true
uses: golangci/golangci-lint-action@v9
with:
version: v2.12.2
- name: Run Go tests
id: gotest
continue-on-error: true
run: go test ./...
- name: Backend check summary
id: backend-summary
if: always()
run: |
golangci_status="${{ steps.golangci.outcome }}"
gotest_status="${{ steps.gotest.outcome }}"
echo "golangci=$golangci_status" >> "$GITHUB_OUTPUT"
echo "gotest=$gotest_status" >> "$GITHUB_OUTPUT"
echo "## Backend Checks" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Check | Result |" >> "$GITHUB_STEP_SUMMARY"
echo "| --- | --- |" >> "$GITHUB_STEP_SUMMARY"
echo "| golangci-lint | $golangci_status |" >> "$GITHUB_STEP_SUMMARY"
echo "| go test ./... | $gotest_status |" >> "$GITHUB_STEP_SUMMARY"
if [ "$golangci_status" != "success" ] || [ "$gotest_status" != "success" ]; then
exit 1
fi
frontend-checks:
name: Frontend Checks
needs: prepare-pr-check
if: needs.prepare-pr-check.outputs.should_run == 'true' && needs.prepare-pr-check.outputs.authorized == 'true'
runs-on: ubuntu-latest
outputs:
lint: ${{ steps.frontend-summary.outputs.lint }}
build: ${{ steps.frontend-summary.outputs.build }}
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
repository: ${{ needs.prepare-pr-check.outputs.checkout_repository }}
ref: ${{ needs.prepare-pr-check.outputs.checkout_ref }}
fetch-depth: 1
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: '24'
- name: Enable Corepack
run: corepack enable
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: |
cd webs
echo "dir=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT"
- name: Cache dependencies
uses: actions/cache@v6
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('webs/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install frontend dependencies
run: |
cd webs
yarn install --immutable
- name: Run frontend lint
id: frontend-lint
continue-on-error: true
run: |
cd webs
yarn run lint
- name: Build frontend
id: frontend-build
continue-on-error: true
run: |
cd webs
yarn run build
- name: Frontend check summary
id: frontend-summary
if: always()
run: |
lint_status="${{ steps.frontend-lint.outcome }}"
build_status="${{ steps.frontend-build.outcome }}"
echo "lint=$lint_status" >> "$GITHUB_OUTPUT"
echo "build=$build_status" >> "$GITHUB_OUTPUT"
echo "## Frontend Checks" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Check | Result |" >> "$GITHUB_STEP_SUMMARY"
echo "| --- | --- |" >> "$GITHUB_STEP_SUMMARY"
echo "| yarn run lint | $lint_status |" >> "$GITHUB_STEP_SUMMARY"
echo "| yarn run build | $build_status |" >> "$GITHUB_STEP_SUMMARY"
if [ "$lint_status" != "success" ] || [ "$build_status" != "success" ]; then
exit 1
fi