Cách Viết 1 Package PHP Thuần Có Tích Hợp Semantic Release

CI/CD cho PHP 8.4 với PHPStan, PHPUnit và Semantic Release trên GitLab


Mục tiêu

Xây dựng một dự án PHP 8.4 thuần (không sử dụng framework) với các thành phần:

  • CI/CD trên GitLab
  • Kiểm tra chất lượng code bằng PHPStan
  • Unit Test bằng PHPUnit
  • Tự động tạo version và release bằng Semantic Release
  • Tự động sinh CHANGELOG.md
  • Tự động tạo GitLab Release và Git Tag

1. Cấu trúc dự án

project/
├── src/
├── tests/
├── composer.json
├── phpstan.neon
├── phpunit.xml
├── .gitlab-ci.yml
├── .releaserc.json
└── package.json

2. Cài đặt Composer

composer.json

{
"name": "yourname/project",
"require": {
"php": "^8.4"
},
"require-dev": {
"phpunit/phpunit": "^11.0",
"phpstan/phpstan": "^1.11"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"test": "phpunit",
"stan": "phpstan analyse"
}
}

Cài đặt dependencies:

composer install

3. Cấu hình PHPStan

phpstan.neon

parameters:
level: 6
paths:
- src
- tests
tmpDir: var/cache/phpstan

Giải thích

Cấu hìnhMô tả
levelMức độ kiểm tra code
pathsCác thư mục cần phân tích
tmpDirThư mục cache

Khuyến nghị: Khi codebase đã ổn định có thể nâng level lên 8 hoặc 9.


4. Cấu hình PHPUnit

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>

<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.0/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">

<testsuites>
<testsuite name="Unit">
<directory>tests</directory>
</testsuite>
</testsuites>

<source>
<include>
<directory>src</directory>
</include>
</source>

<coverage>
<report>
<clover outputFile="coverage.xml"/>
</report>
</coverage>

</phpunit>

5. Cấu hình GitLab CI/CD

.gitlab-ci.yml

Pipeline gồm 3 stage:

install

test

release

Cấu hình đầy đủ

stages:
- install
- test
- release

image: php:8.4-cli

variables:
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache"

cache:
key: ${CI_COMMIT_REF_SLUG}-composer
paths:
- .composer-cache/
- vendor/

before_script:
- apt-get update -yqq
- apt-get install -yqq git unzip libzip-dev
- docker-php-ext-install zip
- curl -sS https://getcomposer.org/installer | php --
--install-dir=/usr/local/bin --filename=composer

install:
stage: install
script:
- composer install --prefer-dist --no-progress

phpstan:
stage: test
script:
- composer install --prefer-dist --no-progress
- vendor/bin/phpstan analyse --no-progress
--error-format=gitlab > phpstan-report.json || vendor/bin/phpstan analyse --no-progress

artifacts:
reports:
codequality: phpstan-report.json
when: always

phpunit:
stage: test
script:
- composer install --prefer-dist --no-progress
- vendor/bin/phpunit --coverage-text --colors=never

coverage: '/^\s*Lines:\s*\d+.\d+\%/'

artifacts:
reports:
junit: coverage.xml
when: always

semantic-release:
stage: release

image: node:20-alpine

rules:
- if: '$CI_COMMIT_BRANCH == "main"'

script:
- npm install --no-save semantic-release
- npm install --no-save @semantic-release/gitlab
- npm install --no-save @semantic-release/git
- npm install --no-save @semantic-release/changelog
- npm install --no-save @semantic-release/commit-analyzer
- npm install --no-save @semantic-release/release-notes-generator

- npx semantic-release

6. Cấu hình Semantic Release

.releaserc.json

{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",

[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],

[
"@semantic-release/gitlab",
{
"gitlabUrl": "https://gitlab.com"
}
],

[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md"
],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
]
}

Cài thêm plugin:

npm install --no-save @semantic-release/git

7. Cấu hình GitLab Variables

Vào:

Settings
└── CI/CD
└── Variables

Tạo biến:

VariableGiá trịMục đích
GITLAB_TOKENPersonal Access Token hoặc Project Access TokenCho phép Semantic Release tạo tag, release và push commit
CI_REGISTRYCó sẵnSử dụng nếu cần build/push Docker image

Quyền cần cấp cho GITLAB_TOKEN

api
write_repository

8. Quy tắc Commit Message

Semantic Release hoạt động dựa trên chuẩn Conventional Commits.

Patch Release (x.x.1)

fix: sửa lỗi validate email
fix: xử lý null pointer

Minor Release (x.1.0)

feat: thêm API đăng nhập
feat: thêm export excel

Major Release (1.0.0 → 2.0.0)

feat!: thay đổi cấu trúc API

BREAKING CHANGE: endpoint response changed

Không tạo Release

docs: cập nhật tài liệu
test: bổ sung unit test
chore: cập nhật dependencies
style: format code

9. Kiểm tra Local trước khi Push

Cài dependencies

composer install

Chạy PHPStan

vendor/bin/phpstan analyse

Chạy PHPUnit

vendor/bin/phpunit

Kiểm tra Semantic Release

npx semantic-release --dry-run

Lệnh này giúp xem trước version sẽ được tạo mà không thực hiện release thật.


10. Luồng hoạt động sau khi Push Code

Developer Push Code

GitLab Pipeline

Install Dependencies

PHPStan Analysis

PHPUnit Testing

Semantic Release

Create Git Tag

Generate CHANGELOG

Create GitLab Release

11. Các lưu ý quan trọng

1. PHPStan Level

level: 6

Đây là mức kiểm tra trung bình.

Khuyến nghị:

LevelMức độ
6Trung bình
8Nghiêm ngặt
9Rất nghiêm ngặt

2. Release chỉ chạy trên branch main

rules:
- if: '$CI_COMMIT_BRANCH == "main"'

Điều này giúp tránh việc tạo release từ các branch feature hoặc develop.


3. Lỗi Permission Denied

Nếu gặp lỗi:

permission denied
403 forbidden

Hãy kiểm tra:

  • GITLAB_TOKEN tồn tại
  • Token chưa hết hạn
  • Có quyền api
  • Có quyền write_repository

4. Tối ưu Pipeline

Có thể cache thêm:

cache:
paths:
- vendor/
- node_modules/

để giảm thời gian chạy pipeline.


Kết quả đạt được

Sau khi hoàn thành cấu hình:

✅ PHPStan chạy tự động trên GitLab
✅ PHPUnit chạy tự động trên GitLab
✅ Pipeline chặn merge nếu test thất bại
✅ Tự động tăng version theo Conventional Commits
✅ Tự động tạo Git Tag
✅ Tự động sinh CHANGELOG.md
✅ Tự động tạo GitLab Release
✅ Hỗ trợ hoàn toàn cho PHP 8.4 và GitLab CI/CD.

Post a Comment

Previous Post Next Post