Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 55 additions & 28 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,55 +15,82 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Check PR title format
- 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'
];

// Title should not be empty or too short
// 1. Title length check
if (!title || title.trim().length < 10) {
errors.push('PR title is too short (minimum 10 characters).');
}

// Title should not exceed 72 characters
if (title.length > 72) {
if (title && title.length > 72) {
errors.push(`PR title is too long (${title.length}/72 characters).`);
}

// Title should follow conventional format: type: description
// Allowed types: feat, fix, refactor, docs, style, test, chore, ci, perf, build, revert
const conventionalRegex = /^(feat|fix|refactor|docs|style|test|chore|ci|perf|build|revert)(\(.+\))?:\s.+/;
if (!conventionalRegex.test(title)) {
// 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: description`\n' +
'Allowed types: feat, fix, refactor, docs, style, test, chore, ci, perf, build, revert\n' +
'Example: `feat: add new transaction validation`'
'PR title must follow conventional format: `type(scope): description`\n' +
' Allowed types: ' + allowedTypes.map(t => `\`${t}\``).join(', ') + '\n' +
' Example: `feat(tvm): add blob opcodes`'
);
}

if (errors.length > 0) {
const message = '### PR Title Check Failed\n\n' + errors.map(e => `- ${e}`).join('\n');
core.setFailed(message);
} else {
core.info('PR title format is valid.');
// 3. No trailing period
if (title && title.endsWith('.')) {
errors.push('PR title should not end with a period (.).');
}

- name: Check PR description
uses: actions/github-script@v7
with:
script: |
const body = context.payload.pull_request.body;
// 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) {
core.setFailed(
'### PR Description Check Failed\n\n' +
'PR description is too short or empty. Please describe what this PR does and why.'
);
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 description is valid.');
core.info('PR lint passed.');
}

build:
Expand Down
102 changes: 89 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Here are some guidelines to get started quickly and easily:
- [Commit Messages](#Commit-Messages)
- [Branch Naming Conventions](#Branch-Naming-Conventions)
- [Pull Request Guidelines](#Pull-Request-Guidelines)
- [PR Title Format](#PR-Title-Format)
- [PR Description](#PR-Description)
- [Special Situations And How To Deal With Them](#Special-Situations-And-How-To-Deal-With-Them)
- [Conduct](#Conduct)

Expand Down Expand Up @@ -165,15 +167,70 @@ Template:
The message header is a single line that contains succinct description of the change containing a `commit type`, an optional `scope` and a subject.

`commit type` describes the kind of change that this commit is providing:
* feat (new feature)
* fix (bug fix)
* docs (changes to documentation)
* style (formatting, missing semi colons, etc. no code change)
* refactor (refactoring production code)
* test (adding or refactoring tests. no production code change)
* chore (updating grunt tasks etc. no production code change)

The `scope` can be anything specifying place of the commit change. For example:`protobuf`,`api`,`test`,`docs`,`build`,`db`,`net`.You can use * if there isn't a more fitting scope.
| Type | Purpose | Example |
|------|---------|---------|
| `feat` | New feature | `feat(tvm): add blob opcodes` |
| `fix` | Bug fix | `fix(db): improve resource management` |
| `docs` | Documentation only | `docs: fix formatting issues in README` |
| `style` | Code style (no logic change) | `style: fix import order and line length` |
| `refactor` | Code refactoring (no behavior change) | `refactor(config): simplify parameters` |
| `test` | Adding or updating tests | `test(vm): add unit tests for opcodes` |
| `chore` | Build tooling, dependencies, etc. | `chore(version): bump to v4.7.8` |
| `ci` | CI/CD configuration | `ci: add PR check workflow` |
| `perf` | Performance improvement | `perf(trie): optimize query performance` |
| `build` | Build system changes | `build: add aarch64 support for RocksDB` |
| `revert` | Reverting a previous commit | `revert: restore ApiUtilTest.java` |

The `scope` is optional and specifies the place or module of the commit change.

#### Module Scopes

| Scope | Description |
|-------|-------------|
| `framework` | Core framework, services, APIs, RPC interfaces |
| `chainbase` | Blockchain storage, state management, database layer |
| `actuator` | Transaction execution engine, smart contract operations |
| `consensus` | Consensus mechanism (DPoS, PBFT) |
| `common` | Common utilities, configuration, shared infrastructure |
| `crypto` | Cryptographic functions, key management, signatures |
| `plugins` | Node tools (Toolkit, ArchiveManifest, database plugins) |
| `protocol` | Protocol definitions, protobuf messages, gRPC contracts |

#### Functional Domain Scopes

| Scope | Description | Example |
|-------|-------------|---------|
| `net` | P2P networking, message handling, peer sync | `feat(net): optimize sync logic` |
| `db` | Database operations, queries, persistence | `fix(db): handle null pointer in query` |
| `vm` / `tvm` | Virtual machine, bytecode execution, EIP impl | `feat(tvm): implement eip-7823` |
| `api` | HTTP/gRPC API endpoints | `fix(api): handle null response` |
| `jsonrpc` | JSON-RPC interface (Ethereum-compatible) | `fix(jsonrpc): support blockHash param` |
| `rpc` | gRPC services and methods | `fix(rpc): handle timeout correctly` |
| `http` | HTTP server and endpoints | `feat(http): add new endpoint` |
| `event` | Event logging and event service | `feat(event): optimize concurrent writes` |
| `config` | Configuration management, feature flags | `refactor(config): simplify parameters` |
| `block` | Block processing, validation, structure | `fix(block): validate block header` |
| `proposal` | On-chain governance proposals | `feat(proposal): add Osaka proposal` |
| `trie` | Merkle tree, state trie operations | `perf(trie): optimize tree query` |
| `log` | Application logging | `refactor(log): reduce noise` |
| `metrics` | Performance monitoring, Prometheus | `feat(metrics): add Prometheus support` |
| `test` | Test infrastructure and utilities | `test(proposal): add unit test cases` |
| `docker` | Docker containerization and deployment | `feat(docker): add ARM64 support` |
| `version` | Version and release management | `chore(version): bump to v4.7.8` |

#### Feature Scopes

| Scope | Description |
|-------|-------------|
| `freezeV2` | Resource delegation / freeze-unfreeze V2 mechanism |
| `DynamicEnergy` | Dynamic energy pricing mechanism |
| `stable-coin` | Stable coin features and operations |
| `reward` | Block producer rewards distribution |
| `lite` | Lite fullnode functionality |
| `toolkit` | Node maintenance tools (Toolkit.jar) |

You can use `*` if there isn't a more fitting scope.

The subject contains a succinct description of the change:
1. Limit the subject line, which briefly describes the purpose of the commit, to 50 characters.
Expand Down Expand Up @@ -204,13 +261,32 @@ If the purpose of this submission is to modify one issue, you need to refer to t
4. Use `feature/` as the prefix of the `feature` branch, briefly describe the feature in the name, and connect words with underline (e.g., feature/new_resource_model, etc.).
### Pull Request Guidelines

#### PR Title Format

PR titles must follow the conventional commit format and will be checked by CI:

```
type(scope): description
```

| Rule | Requirement |
|------|-------------|
| Format | `type: description` or `type(scope): description` |
| Length | 10 ~ 72 characters |
| Type must be one of | `feat` `fix` `refactor` `docs` `style` `test` `chore` `ci` `perf` `build` `revert` |

#### PR Description

- PR description must not be empty, minimum **20 characters**.
- Should explain **what** the PR does and **why**.

#### General Rules

1. Create one PR for one issue.
2. Avoid massive PRs.
3. Write an overview of the purpose of the PR in its title.
4. Write a description of the PR for future reviewers.
5. Elaborate on the feedback you need (if any).
6. Do not capitalize the first letter.
7. Do not put a period (.) in the end.
3. Elaborate on the feedback you need (if any).
4. Do not capitalize the first letter of the description.
5. Do not put a period (.) at the end of the title.



Expand Down
Loading