docs: move type and scope reference to PR guidelines #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Check | |
| on: | |
| pull_request: | |
| branches: [ 'develop', 'release_**' ] | |
| types: [ opened, edited, synchronize, reopened ] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| pr-lint: | |
| name: PR Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate PR title and description | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const title = context.payload.pull_request.title; | |
| const body = context.payload.pull_request.body; | |
| const errors = []; | |
| const warnings = []; | |
| const allowedTypes = ['feat','fix','refactor','docs','style','test','chore','ci','perf','build','revert']; | |
| const knownScopes = [ | |
| 'framework','chainbase','actuator','consensus','common','crypto','plugins','protocol', | |
| 'net','db','vm','tvm','api','jsonrpc','rpc','http','event','config', | |
| 'block','proposal','trie','log','metrics','test','docker','version', | |
| 'freezeV2','DynamicEnergy','stable-coin','reward','lite','toolkit' | |
| ]; | |
| // 1. Title length check | |
| if (!title || title.trim().length < 10) { | |
| errors.push('PR title is too short (minimum 10 characters).'); | |
| } | |
| if (title && title.length > 72) { | |
| errors.push(`PR title is too long (${title.length}/72 characters).`); | |
| } | |
| // 2. Conventional format check | |
| const conventionalRegex = /^(feat|fix|refactor|docs|style|test|chore|ci|perf|build|revert)(\([^)]+\))?:\s.+/; | |
| if (title && !conventionalRegex.test(title)) { | |
| errors.push( | |
| 'PR title must follow conventional format: `type(scope): description`\n' + | |
| ' Allowed types: ' + allowedTypes.map(t => `\`${t}\``).join(', ') + '\n' + | |
| ' Example: `feat(tvm): add blob opcodes`' | |
| ); | |
| } | |
| // 3. No trailing period | |
| if (title && title.endsWith('.')) { | |
| errors.push('PR title should not end with a period (.).'); | |
| } | |
| // 4. Description part should not start with a capital letter | |
| if (title) { | |
| const descMatch = title.match(/^\w+(?:\([^)]+\))?:\s*(.+)/); | |
| if (descMatch) { | |
| const desc = descMatch[1]; | |
| if (/^[A-Z]/.test(desc)) { | |
| errors.push('Description should not start with a capital letter.'); | |
| } | |
| } | |
| } | |
| // 5. Scope validation (warning only) | |
| if (title) { | |
| const scopeMatch = title.match(/^\w+\(([^)]+)\):/); | |
| if (scopeMatch && !knownScopes.includes(scopeMatch[1])) { | |
| warnings.push(`Unknown scope \`${scopeMatch[1]}\`. See CONTRIBUTING.md for known scopes.`); | |
| } | |
| } | |
| // 6. PR description check | |
| if (!body || body.trim().length < 20) { | |
| errors.push('PR description is too short or empty (minimum 20 characters). Please describe what this PR does and why.'); | |
| } | |
| // Output warnings | |
| for (const w of warnings) { | |
| core.warning(w); | |
| } | |
| // Output result | |
| if (errors.length > 0) { | |
| const docLink = 'See [CONTRIBUTING.md](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '/blob/develop/CONTRIBUTING.md#pull-request-guidelines) for details.'; | |
| const message = '### PR Lint Failed\n\n' + errors.map(e => `- ${e}`).join('\n') + '\n\n' + docLink; | |
| core.setFailed(message); | |
| } else { | |
| core.info('PR lint passed.'); | |
| } | |
| build: | |
| name: Build (JDK ${{ matrix.java }} / ${{ matrix.arch }}) | |
| needs: pr-lint | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - java: '8' | |
| runner: ubuntu-latest | |
| arch: x86_64 | |
| - java: '17' | |
| runner: ubuntu-24.04-arm | |
| arch: aarch64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK ${{ matrix.java }} | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: ${{ matrix.java }} | |
| distribution: 'temurin' | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-${{ matrix.arch }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle-wrapper.properties') }} | |
| restore-keys: ${{ runner.os }}-${{ matrix.arch }}-gradle- | |
| - name: Build | |
| run: ./gradlew clean build -x test | |
| checkstyle: | |
| name: Checkstyle | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK 8 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '8' | |
| distribution: 'temurin' | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle-wrapper.properties') }} | |
| restore-keys: ${{ runner.os }}-gradle- | |
| - name: Run Checkstyle | |
| run: ./gradlew :framework:checkstyleMain :framework:checkstyleTest :plugins:checkstyleMain | |
| - name: Upload Checkstyle reports | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: checkstyle-reports | |
| path: | | |
| framework/build/reports/checkstyle/ | |
| plugins/build/reports/checkstyle/ | |
| test: | |
| name: Unit Tests (JDK ${{ matrix.java }} / ${{ matrix.arch }}) | |
| runs-on: ${{ matrix.runner }} | |
| needs: build | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - java: '8' | |
| runner: ubuntu-latest | |
| arch: x86_64 | |
| - java: '17' | |
| runner: ubuntu-24.04-arm | |
| arch: aarch64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK ${{ matrix.java }} | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: ${{ matrix.java }} | |
| distribution: 'temurin' | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-${{ matrix.arch }}-gradle-${{ hashFiles('**/*.gradle', '**/gradle-wrapper.properties') }} | |
| restore-keys: ${{ runner.os }}-${{ matrix.arch }}-gradle- | |
| - name: Run tests | |
| run: ./gradlew test | |
| - name: Upload test reports | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-reports-${{ matrix.arch }} | |
| path: | | |
| **/build/reports/tests/ |