{"id":20144190,"url":"https://github.com/quansitech/qsci","last_synced_at":"2025-08-24T01:07:00.741Z","repository":{"id":97656383,"uuid":"192318203","full_name":"quansitech/qsci","owner":"quansitech","description":"基于云效和swoole构建的轻量级持续集成方案","archived":false,"fork":false,"pushed_at":"2019-07-16T14:31:41.000Z","size":98,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-13T10:50:10.266Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quansitech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.996ICU","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-17T09:39:03.000Z","updated_at":"2019-12-30T05:07:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"ad9c994d-d946-4697-8db7-cc3dce2f7a7f","html_url":"https://github.com/quansitech/qsci","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quansitech%2Fqsci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quansitech%2Fqsci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quansitech%2Fqsci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quansitech%2Fqsci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quansitech","download_url":"https://codeload.github.com/quansitech/qsci/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241587914,"owners_count":19986627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T22:09:07.800Z","updated_at":"2025-03-02T23:44:05.211Z","avatar_url":"https://github.com/quansitech.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 基于云效和swoole构建的轻量级持续集成方案\n![lincense](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)\n[![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n![Pull request welcome](https://img.shields.io/badge/pr-welcome-green.svg?style=flat-square)\n\n### 相关概念\n+ #### 持续集成\n    是一种互联网开发快速迭代流程，频繁地将最新代码合并到主干，降低合并代码合并主干的难度，同时又更加容易的发现和修复问题。\n    和持续集成相关的还有持续交付、持续部署。\n+ #### 云效\n    云效是阿里云提供的一站式企业协同研发平台，其提供了需求、迭代、缺陷、文档、流水线等跟项目开发有关的一系列管理工具，目前处于免费使用阶段。\n+ #### swoole\n    swoole是一个为php提供网络通信和异步io的扩展，目前也支持协程开发。本身提供强大的http服务功能，采用swoole作为微服务开发非常有优势。\n    \n### 为什么\n+ #### 为什么是云效 \n   了解过持续集成的同学可能还知道jenkins、drone，这些都是目前最流行的持续集成工具。作者也做了大量的学习研究对比。那么为什么最后选择了云效呢？\n   作者的公司是以小型外包项目为主的公司，讲求可管理高效低成本。而云效除流水线任务功能外还有强大的项目管理功能，对没有特殊需求的公司是完全免费的。\n   同时对于不太复杂的项目，测试环境的构建流程也不是特别的需求，只需要用到自定义脚本能触发一系列的自定义任务即可。如代码更新、自动化测试。还可以\n   大大降低流水线的运行时间。因此作者综合评估后觉得云效更适合。\n+ #### 为什么是swoole\n   swoole自带web服务功能，这对于搭配docker快速构建运行环境非常方便，只需安装php及swoole扩展即可，swoole在构建微服务方面有天然优势。\n   此外，swoole自带的Process在实现与子进程的IO输出交互时比使用shell_exec等函数要方便许多。可实现脚本运行时，可马上将任务执行的每个情况\n   立即显示到流水线的执行日志。\n   \n### 效果图\n\u003cimg src=\"https://github.com/tiderjian/qsci/blob/master/blob/ex.png\" /\u003e\n\n### 安装\n```php\ngit clone https://github.com/tiderjian/qsci.git\n```\n\n### 启动server.php前的一些设置\n+ #### TOKEN常量\n    验证请求的合法性\n+ #### PORT常量\n    web服务监听的端口号\n+ #### ERROR_PREFIX与ERROR_SUFFIX\n    云效用于定位任务是否执行出错的字符，如没有特别需求，使用默认的即可\n+ #### swoole webserver的配置\n    同一时间一个项目只能执行一个流水线任务，如果有新的任务触发，旧任务会立即结束，因此采用单进程模式处理任务，切勿修改。（要处理多个项目的流水线，\n    可为每一个项目启动一个docker容器）\n    \n ### 运行swoole服务\n 强烈建议将服务运行于docker容器中，1、方便安装。 2、当要处理多个项目的流水线时，可分别创建对应的docker，隔离运行环境。\n ```php\n php server.php\n ```\n   \n### 流程图\n \u003cimg src=\"https://user-images.githubusercontent.com/1665649/59674504-fbdb9e80-91f5-11e9-8526-ffa535d334e2.png\" /\u003e\n    \n### 创建任务\n+ #### 创建任务文件夹\n    在TaskProviders文件夹下新增任务名+Provider的文件夹，如任务名为example，文件夹为ExampleProvider。之后创建的所有脚本文件，任务类都将放于该文件夹下。\n    \n+ #### 创建任务类\n    以创建Example任务为例\n    ```php\n    \u003c?php\n    namespace QSCI\\TaskProviders\\ExampleProvider;\n    \n    use QSCI\\TaskManager;\n    use QSCI\\TaskProviders\\Provider;\n    use Swoole\\Http\\Request;\n    use Swoole\\Process;\n    \n     /**\n     * 必须继承Provider接口，并实现sign和init方法\n     */\n    class Example implements Provider{\n    \n        //与请求的action参数对应，如该sign返回字符串与action一致，则会触发该任务运行\n        public function sign() : string\n        {\n            return 'example';\n        }\n    \n        //具体的任务执行内容\n        public function init(Request $request, TaskManager $manager)\n        {\n              .\n              .\n              .\n        }\n    }\n    ```\n+ #### 实现具体的任务执行逻辑\n    在任务类的init方法中编写具体的任务执行代码，以创建一个拉取最新代码，并删除缓存的任务为例\n    ```php\n    //获取请求参数\n    $project_name = $request-\u003epost['project'];\n    \n    //参数安全过滤\n    if(!preg_match(\"/^[A-Za-z0-9_\\/\\-]+$/\", $project_name)){\n        throw new Exception('invalid project name');\n    }\n\n    $branch = $request-\u003epost['branch'];\n    //参数安全过滤\n    if (!preg_match(\"/^[A-Za-z0-9_\\-@]+$/\", $branch)) {\n        throw new Exception('invalid branch');\n    }\n\n    //向任务管理器添加一条具体的任务\n    //new Task对象\n   //Task对象第一个参数为任务执行的闭包函数，闭包函数第一个参数返回一个swoole的Process对象。\n   //Task对象第二个参数为任务出现异常返回的错误提示。\n   //Task对象第三个参数为任务正常结束返回的成功提示。\n   //Process是swoole的进程管理器，我们这里用到它的exec方法，和php的shell_exec方法功能一样，可执行一个系统命令，它有良好的输出IO处理\n   //exec方法第一个参数为要调用的系统命令绝对路径，后面的数组是各个参数的集合，exec(命令，[参数1，参数2，参数3, ....]) =  命令 参数1 参数2 参数3....\n   //Process的详细用法查阅swoole文档\n    $manager-\u003eaddTask(new Task(function (Process $worker) use ($project_name, $branch) {\n        $worker-\u003eexec('/bin/sh', [__DIR__ . '/gitPull.sh', \"/app/{$project_name}\", $branch]);\n    }, 'git pull error!', 'git pull finished!'));\n\n    //设置清空缓存任务\n    $manager-\u003eaddTask(new Task(function (Process $worker) use ($project_name) {\n        $dir = \"/app/{$project_name}/app/Runtime\";\n        if (file_exists($dir)) {\n            $worker-\u003eexec('/bin/rm', [\"-rf\", \"{$dir}/*\"]);\n        }\n    }, 'clear runtime failed!', 'clear runtime finished!'));\n    ```\n    \n ### 配置云效\n 云效的流水线配置方法请自行阅读阿里云的学习文档，这里只给出云效的自定义脚本代码\n ```blade\ncurl -d \"post参数\" \"http://url地址?token=你设置的token\u0026action=example\" | tee test.log\nst=`grep -c \"ERROR\\*\\*\\*\\*\\*.*\\*\\*\\*\\*\\*ERROR\" test.log`\nif [ $st -gt 0 ]; then\n    exit 1\nfi\n```\n    \n### lincense\n[MIT License](https://github.com/tiderjian/qsci/blob/master/LICENSE.MIT) AND [996ICU License](https://github.com/tiderjian/qsci/blob/master/LICENSE.996ICU)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquansitech%2Fqsci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquansitech%2Fqsci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquansitech%2Fqsci/lists"}