name: PR Checks on: pull_request: types: [opened, synchronize, reopened, edited] branches: - dev - main jobs: # Validate PR title and description validate-pr: name: Validate PR Format runs-on: ubuntu-latest steps: - name: Check PR title format uses: amannn/action-semantic-pull-request@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: types: | feat fix docs style refactor perf test chore ci security scopes: | exchange trader ai api ui frontend backend security deps requireScope: false - name: Check PR size uses: actions/github-script@v7 with: script: | const pr = context.payload.pull_request; const additions = pr.additions; const deletions = pr.deletions; const total = additions + deletions; let label = ''; let comment = ''; if (total < 300) { label = 'size: small'; comment = '✅ This PR is **small** and easy to review!'; } else if (total < 1000) { label = 'size: medium'; comment = '⚠️ This PR is **medium** sized. Consider breaking it into smaller PRs if possible.'; } else { label = 'size: large'; comment = '🚨 This PR is **large** (>' + total + ' lines changed). Please consider breaking it into smaller, focused PRs for easier review.'; } // Add size label await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, labels: [label] }); // Add comment for large PRs if (total >= 1000) { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, body: comment }); } # Backend tests backend-tests: name: Backend Tests (Go) runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.21' - name: Install TA-Lib run: | sudo apt-get update sudo apt-get install -y libta-lib-dev - name: Cache Go modules uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Download dependencies run: go mod download - name: Run go fmt run: | if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then echo "Please run 'go fmt' on your code" gofmt -s -l . exit 1 fi - name: Run go vet run: go vet ./... - name: Run tests run: go test -v -race -coverprofile=coverage.out ./... - name: Build run: go build -v -o nofx - name: Upload coverage uses: codecov/codecov-action@v4 with: file: ./coverage.out flags: backend # Frontend tests frontend-tests: name: Frontend Tests (React/TypeScript) runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Cache Node modules uses: actions/cache@v4 with: path: web/node_modules key: ${{ runner.os }}-node-${{ hashFiles('web/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - name: Install dependencies working-directory: ./web run: npm ci - name: Run linter working-directory: ./web run: npm run lint - name: Run type check working-directory: ./web run: npm run type-check || true # Don't fail on type errors for now - name: Build working-directory: ./web run: npm run build # Auto-label based on files changed auto-label: name: Auto Label PR runs-on: ubuntu-latest permissions: pull-requests: write steps: - uses: actions/labeler@v5 with: configuration-path: .github/labeler.yml repo-token: ${{ secrets.GITHUB_TOKEN }} # Check for security issues security-check: name: Security Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy results uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: 'trivy-results.sarif' # Check for secrets in code secrets-check: name: Check for Secrets runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run Gitleaks uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # All checks passed all-checks: name: All Checks Passed runs-on: ubuntu-latest needs: [validate-pr, backend-tests, frontend-tests, security-check, secrets-check] if: always() steps: - name: Check all jobs run: | if [ "${{ contains(needs.*.result, 'failure') }}" == "true" ]; then echo "Some checks failed" exit 1 else echo "All checks passed!" fi