p3c-pmd Overview
p3c-pmd is a static code analysis tool that enforces Alibaba's Java coding stanndards. It extends the open-source PMD framework to specifically check for violations of the Alibaba Java Development Guidelines.
PMD Architecture
PMD operates by:
- Parsing source code into a Abstract Syntax Tree (AST)
- Appplying rule sets to traverse and analyze the AST nodes
- Flagging violations based on predefined patterns
p3c-pmd implements custom Java rules and XPath expressions to validate code against Alibaba's standards.
GitLab Integration Implementation
Server Hooks Configuration
GitLab provides three primary server hooks:
pre-receive: Executes before accepting pushes (used for validation)update: Runs per branch being updatedpost-receive: Executes after successful pushes
Key environment variables available in hooks:
| Variable | Description |
|---|---|
GL_ID |
User identifier (e.g., user-2234) |
GL_REPOSITORY |
Project identifier (e.g., project-787) |
GL_USERNAME |
GitLab username |
Installation Steps
- Build p3c-pmd from source:
cd p3c-pmd
mvn clean package
- Configure GitLab hook:
# Project-specific
mkdir -p /path/to/repo.git/custom_hooks/pre-receive.d
# Global configuration
mkdir -p /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d
Pre-receive Hook Implementation
The hook performs:
- Diff analysis to identify modified Java files
- p3c-pmd execution against changed files
- Access control via whitelist/blacklist
Sample hook script:
#!/bin/bash
JAVA_HOME=/usr/local/jdk-18
PMD_JAR=/path/to/p3c-pmd.jar
RULESET=/path/to/rulesets/all-rule.xml
# Check project against blacklist
if grep -qw "${GL_REPOSITORY}" /path/to/blacklist.txt; then
while read oldrev newrev refname; do
changed_files=$(git diff --name-only ${oldrev} ${newrev} | grep '.java$')
if [ -n "$changed_files" ]; then
temp_dir=$(mktemp -d)
for file in $changed_files; do
mkdir -p "${temp_dir}/$(dirname ${file})"
git show ${newrev}:${file} > "${temp_dir}/${file}"
done
java -jar $PMD_JAR -d $temp_dir -R $RULESET -f text
result=$?
if [ $result -ne 0 ]; then
if grep -qw "${GL_USERNAME}" /path/to/whitelist.txt || \
grep -qw "${GL_REPOSITORY}" /path/to/project-whitelist.txt; then
result=0
fi
fi
rm -rf $temp_dir
exit $result
fi
done
fi
exit 0
Access Control Configuration
Whitelist example (user-whitelist.txt):
developer1
developer2
Project blacklist example (project-blacklist.txt):
project-123
project-456