添加完整 CI/CD 流程
- Gitea Actions 配置 (.gitea/workflows/ci.yml) - PHPUnit 测试框架 (composer.json, phpunit.xml) - 示例测试用例 (tests/Unit, tests/Feature) - .gitignore 配置 流程说明: 1. feature/* 分支 push → 部署测试环境 → 运行测试 2. 测试失败 → 自动回退 + 通知 3. 测试通过 → 自动合并到 main → 部署正式环境 4. main 分支 push → 直接部署正式环境 需要配置 Secrets: - DEPLOY_KEY: SSH 私钥 - GITEA_TOKEN: 用于自动合并的 Token
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
# 依赖
|
||||
/vendor/
|
||||
|
||||
# 测试缓存
|
||||
/.phpunit.cache/
|
||||
/coverage/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# 系统文件
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# 环境配置
|
||||
.env
|
||||
.env.local
|
||||
config.local.php
|
||||
|
||||
# 用户数据目录 (每个用户独立)
|
||||
/*/
|
||||
|
||||
# 但保留这些目录
|
||||
!/deploy/
|
||||
!/tests/
|
||||
!/src/
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "starmen1265/kb-web",
|
||||
"description": "知识库网页系统",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit --testdox",
|
||||
"test:coverage": "phpunit --coverage-html coverage"
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
cacheDirectory=".phpunit.cache">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory>tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
<directory suffix=".php">.</directory>
|
||||
<exclude>vendor</exclude>
|
||||
<exclude>tests</exclude>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* 功能测试 - 安全检查
|
||||
*/
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SecurityTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* 测试配置文件不暴露敏感信息
|
||||
*/
|
||||
public function testConfigDoesNotExposePassword(): void
|
||||
{
|
||||
$config = file_get_contents(__DIR__ . '/../../config.php');
|
||||
|
||||
// 确保没有硬编码的真实密码
|
||||
$this->assertStringNotContainsString('123456', $config, '配置中不应包含简单密码');
|
||||
$this->assertStringNotContainsString('password', strtolower($config), '配置中不应包含 password 字符串');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 SQL 注入防护
|
||||
*/
|
||||
public function testConfigUsesPreparedStatements(): void
|
||||
{
|
||||
$config = file_get_contents(__DIR__ . '/../../config.php');
|
||||
|
||||
// 确保使用 PDO 预处理
|
||||
$this->assertStringContainsString('prepare', $config, '应该使用 PDO 预处理语句');
|
||||
$this->assertStringContainsString('execute', $config, '应该使用 execute 执行预处理');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 XSS 防护
|
||||
*/
|
||||
public function testOutputUsesHtmlspecialchars(): void
|
||||
{
|
||||
$files = [
|
||||
__DIR__ . '/../../dashboard.php',
|
||||
__DIR__ . '/../../view.php',
|
||||
];
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
$this->assertStringContainsString('htmlspecialchars', $content,
|
||||
basename($file) . ' 应该使用 htmlspecialchars 防止 XSS');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 Session 安全
|
||||
*/
|
||||
public function testSessionSecurity(): void
|
||||
{
|
||||
$config = file_get_contents(__DIR__ . '/../../config.php');
|
||||
|
||||
// 确保有 session 检查
|
||||
$this->assertStringContainsString('session', strtolower($config), '应该有 session 相关配置');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* 示例单元测试
|
||||
*/
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ConfigTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* 测试配置文件存在
|
||||
*/
|
||||
public function testConfigFileExists(): void
|
||||
{
|
||||
$this->assertFileExists(__DIR__ . '/../../config.php', '配置文件应该存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试样式文件存在
|
||||
*/
|
||||
public function testStyleFileExists(): void
|
||||
{
|
||||
$this->assertFileExists(__DIR__ . '/../../style.css', '样式文件应该存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试入口文件存在
|
||||
*/
|
||||
public function testIndexFileExists(): void
|
||||
{
|
||||
$this->assertFileExists(__DIR__ . '/../../index.php', '入口文件应该存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试仪表盘文件存在
|
||||
*/
|
||||
public function testDashboardFileExists(): void
|
||||
{
|
||||
$this->assertFileExists(__DIR__ . '/../../dashboard.php', '仪表盘文件应该存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试查看文件存在
|
||||
*/
|
||||
public function testViewFileExists(): void
|
||||
{
|
||||
$this->assertFileExists(__DIR__ . '/../../view.php', '查看文件应该存在');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPUnit bootstrap file
|
||||
*/
|
||||
|
||||
// 定义测试环境常量
|
||||
define('TESTING', true);
|
||||
|
||||
// 加载配置(测试环境)
|
||||
if (file_exists(__DIR__ . '/../config.php')) {
|
||||
// 可以创建一个测试用的 config.test.php
|
||||
// require_once __DIR__ . '/../config.test.php';
|
||||
}
|
||||
|
||||
// 自动加载
|
||||
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
}
|
||||
Reference in New Issue
Block a user