{"id":284572,"date":"2017-04-06T20:25:02","date_gmt":"2017-04-06T16:25:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=284572"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=284572","title":{"rendered":"\u0421\u0435\u0442\u0438 \u041f\u0435\u0442\u0440\u0438 \u0441 Symfony \u0430-\u043b\u044f WorkFlow \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442"},"content":{"rendered":"<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 GitHub, \u043a\u0443\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c Pull Request. \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0442 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043d \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0438 \u043c\u0435\u0440\u0436\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. <\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d5e\/31d\/7ae\/d5e31d7ae428fc3d22a2d02226d8ad06.png\" alt=\"image\"\/><\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043f\u043e\u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u0442\u043e \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0430\u0440\u0438\u0446\u0430\u0446\u0438\u0438 \u043d\u0430\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u043b, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c \u043e WorkFlow \u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0442\u0437:<br \/>  1. \u041e\u0442\u043a\u0440\u044b\u0442<br \/>  2. \u041d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0432 Travis CI, \u043f\u0440\u0438\u0447\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0442\u0443\u0434\u0430 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c Pull Request, \u0432\u0435\u0434\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c-\u0442\u043e \u043d\u0430\u0434\u043e \u0432\u0441\u0435, \u043d\u0435 \u0442\u0430\u043a \u043b\u0438?<br \/>  3. \u0416\u0434\u0435\u0442 Review \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 Travis CI<br \/>  3.1 \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043a\u043e\u0434\u0430 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 Travis CI<br \/>  4. \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 Review<br \/>  5. \u041f\u0440\u0438\u043d\u044f\u0442 \u043f\u043e\u0441\u043b\u0435 Review<br \/>  6. \u0421\u043c\u0435\u0440\u0436\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  7. \u041e\u0442\u043a\u043b\u043e\u043d\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  8. \u0417\u0430\u043a\u0440\u044b\u0442 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  9. \u041e\u0442\u043a\u0440\u044b\u0442 \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u0437\u0430\u043a\u0440\u044b\u0442, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043e Review<br \/>  10. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u00ab\u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\u00bb, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043e Review, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043e\u043d \u0441\u043d\u043e\u0432\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 Travis CI (\u043f\u0443\u043d\u043a\u0442 2), \u0430 \u043e\u0442 Review \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441 \u043d\u0438\u043c \u0441\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u044b\u0448\u0435<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0416\u0435\u0441\u0442\u044c, \u043f\u0440\u0430\u0432\u0434\u0430?<\/p>\n<p>  \u0422\u043e, \u0447\u0442\u043e \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430\u0445 \u2014 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438, \u0442\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0432\u0441\u0451 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u0440\u0443\u0433\u0430\u0445 \u2014 \u044d\u0442\u043e \u0442\u0435 \u0441\u0430\u043c\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0432\u0435\u0434\u0435\u043c \u0440\u0435\u0447\u044c. \u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u2014 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0441\u0440\u0430\u0437\u0443) \u0432 \u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.<br \/>  \u0417\u0434\u0435\u0441\u044c \u0438 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u0438\u0433\u0440\u0443 WorkFlow \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u043d\u0430\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0421\u043c\u044b\u0441\u043b \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u0430\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u044f, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u0430\u043b\u0438\u0434\u0435\u043d \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <br \/>  \u0415\u0441\u043b\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0442\u043e \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043c\u0435\u0440\u0436\u0435\u043d, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u043f\u0440\u043e\u0448\u0435\u043b \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u041e\u0411\u042f\u0417\u0410\u0422\u0415\u041b\u042c\u041d\u042b\u0419 \u043f\u0443\u0442\u044c \u0434\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 (\u043e\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432 \u0442\u0440\u0435\u0432\u0438\u0441 \u0438 \u0440\u0435\u0432\u044c\u044e \u0434\u043e \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043c\u0435\u0440\u0436\u0430). <\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c PullRequest \u0438 \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0438\u0437 \u043e\u0434\u043d\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0432 \u0434\u0440\u0443\u0433\u0438\u0435. <\/p>\n<pre><code class=\"php\">namespace AppBundle\\Entity;  use Doctrine\\ORM\\Mapping as ORM;  \/**  * @ORM\\Table(name=&quot;pull_request&quot;)  * @ORM\\Entity(repositoryClass=&quot;AppBundle\\Repository\\PullRequestRepository&quot;)  *\/ class PullRequest {     \/**      * @ORM\\Column(name=&quot;id&quot;, type=&quot;integer&quot;)      * @ORM\\Id      * @ORM\\GeneratedValue(strategy=&quot;AUTO&quot;)      *\/     private $id;      \/**      * @ORM\\Column(type=&quot;string&quot;)      *\/     private $currentPlace;       \/**      * @return int      *\/     public function getId()     {         return $this-&gt;id;     }      \/**      * @return PullRequest      *\/     public function setCurrentPlace($currentPlace)     {         $this-&gt;currentPlace = $currentPlace;          return $this;     }      \/**      * @return string      *\/     public function getCurrentPlace()     {         return $this-&gt;currentPlace;     } } <\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0442\u044b \u0437\u043d\u0430\u0435\u0448\u044c \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 WorkFlow:  <\/p>\n<pre><code># app\/config\/config.yml framework:     workflows:         pull_request:             type: 'state_machine'             marking_store:                 type: 'single_state'                 argument: 'currentPlace'             supports:                 - AppBundle\\Entity\\PullRequest             places:                 - start                 - coding                 - travis                 - review                 - merged                 - closed             transitions:                 submit:                     from: start                     to: travis                 update:                     from: [coding, travis, review]                     to: travis                 wait_for_review:                     from: travis                     to: review                 request_change:                     from: review                     to: coding                 accept:                     from: review                     to: merged                 reject:                     from: review                     to: closed                 reopen:                     from: closed                     to: review <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435, \u043c\u044b \u0437\u0430\u0434\u0430\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0431\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c (framework.workflow.pull_request.places): start, coding, travis, review, merged, closed \u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 (framework.workflow.pull_request.transactions) \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c, \u043f\u0440\u0438 \u043a\u0430\u043a\u043e\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 \u044d\u0442\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435: submit, update, wait_for_review, request_change, accept, reject, reopen.<\/p>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u0436\u0438\u0437\u043d\u044c:<br \/>  Submit \u2014 \u044d\u0442\u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0438\u0437 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 Travis CI. <br \/>  <i>\u042d\u0442\u043e \u043d\u0430\u0448\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0444\u043e\u0440\u043c\u043b\u044f\u0435\u043c \u043d\u0430\u0448 \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u0438 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e Travis CI \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u044c.<\/i><\/p>\n<p>  Update \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 coding (\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430), travis (\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 Travis CI), review (\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 review \u043a\u043e\u0434\u0430) \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 Travis. <br \/>  <i>\u042d\u0442\u043e \u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u043e\u0432\u0430 \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043d\u0430\u0448\u0435\u043c pull request, \u0442.\u00a0\u0435. \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043c\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0442\u0435\u0440.<\/i><\/p>\n<p>  Wait For Review \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Travis \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Review. <br \/>  <i>\u0422\u043e \u0431\u0438\u0448\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u0430\u043f\u0443\u0448\u0438\u043b\u0438 \u0441\u0432\u043e\u0439 \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u0438 \u043e\u043d \u0443\u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d Travis-\u043e\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u043d\u0430 \u043d\u0430\u0448 \u043a\u043e\u0434 \u2014 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0440\u0435\u0432\u044c\u044e \u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0447\u0442\u043e \u0441 \u044d\u0442\u0438\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.<\/i><\/p>\n<p>  Request_Change \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437 Review \u0432 Coding. <br \/>  <i>\u0422.\u0435. \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443) \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c \u0442\u043e, \u043a\u0430\u043a \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043e\u043d\u0438 \u0445\u043e\u0442\u044f\u0442 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438 \u043c\u044b \u0432\u043d\u043e\u0441\u0438\u043c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0441\u043d\u043e\u0432\u0430.<\/i><\/p>\n<p>  Accept \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437 Review \u0432 Merged, \u043a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0441\u0435\u0431\u044f \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439.<br \/>  <i>\u041c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043d\u0430\u0448\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438 \u043e\u043d\u0438 \u0435\u0433\u043e \u043c\u0435\u0440\u0436\u0430\u0442 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442.<\/i><\/p>\n<p>  Reject \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437 Review \u0432 Closed.<br \/>  <i>\u041c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u043d\u0435 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u043d\u0443\u0436\u043d\u044b\u043c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430\u0448 pull request \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c.<\/i><\/p>\n<p>  Reopen \u2014 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0421losed \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Review.<br \/>  <i>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0430 \u043d\u0430\u0448 \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u0438 \u0440\u0435\u0448\u0438\u043b\u0430 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c.<\/i><\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0436\u0435 \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u0430\u043a\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u0434:  <\/p>\n<pre><code class=\"php\">use AppBundle\\Entity\\PullRequest; use Symfony\\Component\\Workflow\\Exception\\LogicException;  $pullRequest = new PullRequest(); \/\/\u0441\u043e\u0432\u0441\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442  $stateMachine = $this-&gt;getContainer()-&gt;get('state_machine.pull_request'); $stateMachine-&gt;can($pullRequest, 'submit'); \/\/true $stateMachine-&gt;can($pullRequest, 'accept'); \/\/false  try {     \/\/\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f start \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 travis     $stateMachine-&gt;apply($pullRequest, 'submit'); } catch(LogicException $workflowException) {}  $stateMachine-&gt;can($pullRequest, 'update'); \/\/true $stateMachine-&gt;can($pullRequest, 'wait_for_review'); \/\/true $stateMachine-&gt;can($pullRequest, 'accept'); \/\/false  try {     \/\/\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f update \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 review     $stateMachine-&gt;apply($pullRequest, 'wait_for_review'); } catch(LogicException $workflowException) {}  $stateMachine-&gt;can($pullRequest, 'request_change'); \/\/true $stateMachine-&gt;can($pullRequest, 'accept'); \/\/true $stateMachine-&gt;can($pullRequest, 'reject'); \/\/true $stateMachine-&gt;can($pullRequest, 'reopen'); \/\/false  try {     \/\/\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f update \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 review     $stateMachine-&gt;apply($pullRequest, 'reject'); } catch(LogicException $workflowException) {}  $stateMachine-&gt;can($pullRequest, 'request_change'); \/\/false $stateMachine-&gt;can($pullRequest, 'accept'); \/\/false $stateMachine-&gt;can($pullRequest, 'reject'); \/\/false $stateMachine-&gt;can($pullRequest, 'reopen'); \/\/true - \u043c\u043e\u0436\u0435\u043c \u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044c pull request  echo $pullRequest-&gt;getCurrentPlace(); \/\/closed  try {     \/\/\u043d\u0430\u0440\u0443\u0448\u0438\u043c \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0443 - \u0437\u0430\u043a\u0440\u043e\u0435\u043c \u0438 \u0442\u0430\u043a \u0443\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442     $stateMachine-&gt;apply($pullRequest, 'reject'); } catch(LogicException $workflowException) {     echo '\u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043c\u044b \u0441\u0431\u0438\u043b\u0438\u0441\u044c!!! :('; }  $stateMachine-&gt;apply($pullRequest, 'reopen'); echo $pullRequest-&gt;getCurrentPlace(); \/\/review <\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0435\u0441\u043b\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0442\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0431\u044b\u0432\u0430\u0435\u0442 \u0442\u0430\u043a, \u0447\u0442\u043e \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u041f\u043e\u043c\u0438\u043c\u043e state_machine \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0448\u0435\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0442\u0438\u043f workflow, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 \u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u041f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0438\u0437 \u0436\u0438\u0437\u043d\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u043b\u0443\u0436\u0438\u0442\u044c \u0432\u0430\u0448\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u0430 \u0445\u0430\u0431\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u00ab\u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u043b\u0430\u0433\u0438\u0430\u0442\u00bb, \u00ab\u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u00bb \u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0441\u0442\u0430\u0442\u0443\u0441 \u00ab\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u0430\u00bb \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0432\u0441\u0435 \u044d\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u044b, \u043d\u0443 \u044d\u0442\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0432\u0441\u0435 \u044d\u0442\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u043d\u043e \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u0435\u0434\u0435\u043c \u0440\u0435\u0447\u044c \u043d\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c. <\/p>\n<p>  \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c Article \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435.  <\/p>\n<pre><code class=\"php\">use Doctrine\\ORM\\Mapping as ORM;  \/**  * @ORM\\Table(name=&quot;article&quot;)  * @ORM\\Entity(repositoryClass=&quot;AppBundle\\Repository\\ArticleRepository&quot;)  *\/ class Article {     \/**      * @ORM\\Column(name=&quot;id&quot;, type=&quot;integer&quot;)      * @ORM\\Id      * @ORM\\GeneratedValue(strategy=&quot;AUTO&quot;)      *\/     private $id;      \/**      * @ORM\\Column(type=&quot;simple_array&quot;)      *\/     private $currentPlaces;           public function getId()     {         return $this-&gt;id;     }      public function setCurrentPlaces($currentPlaces)     {         $this-&gt;currentPlaces = $currentPlaces;          return $this;     }          public function getCurrentPlaces()     {         return $this-&gt;currentPlaces;     } } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0433\u043e WorkFlow \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e:  <\/p>\n<pre><code>article:             supports:                 - AppBundle\\Entity\\Article             type: 'workflow'             marking_store:                 type: 'multiple_state'                 argument: 'currentPlaces'             places:                 - draft                 - wait_for_journalist                 - approved_by_journalist                 - wait_for_spellchecker                 - approved_by_spellchecker                 - published             transitions:                 request_review:                     from: draft                     to:                         - wait_for_journalist                         - wait_for_spellchecker                 journalist_approval:                     from: wait_for_journalist                     to: approved_by_journalist                 spellchecker_approval:                     from: wait_for_spellchecker                     to: approved_by_spellchecker                 publish:                     from:                         - approved_by_journalist                         - approved_by_spellchecker                     to: published <\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0431\u0443\u0434\u0438\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434:  <\/p>\n<pre><code class=\"php\">$article = new Article(); $workflow = $this-&gt;getContainer()-&gt;get('workflow.article');  $workflow-&gt;apply($article, 'request_review'); \/*    array(2) {       [&quot;wait_for_journalist&quot;]=&gt;       int(1)       [&quot;wait_for_spellchecker&quot;]=&gt;       int(1)     }  *\/ var_dump($article-&gt;getCurrentPlaces());  \/\/\u041e\u043a\u0435\u0439, \u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0441\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u043d\u043e\u0432\u043e\u0441\u0442\u044c! $workflow-&gt;apply($article, 'journalist_approval');  \/*    array(2) {       [&quot;wait_for_spellchecker&quot;]=&gt;       int(1)       [&quot;approved_by_journalist&quot;]=&gt;       int(1)     }  *\/ var_dump($article-&gt;getCurrentPlaces()); var_dump($workflow-&gt;can($article, 'publish')); \/\/false, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430  $workflow-&gt;apply($article, 'spellchecker_approval'); var_dump($workflow-&gt;can($article, 'publish')); \/\/true, \u0432\u0441\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u044b <\/code><\/pre>\n<p>  \u0412\u044b \u0442\u0430\u043a \u0436\u0435 \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"http:\/\/www.graphviz.org\">www.graphviz.org<\/a> \u2014 \u041f\u041e \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0440\u0430\u0444\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0430:  <\/p>\n<pre><code>digraph workflow {   ratio=&quot;compress&quot; rankdir=&quot;LR&quot;   node [fontsize=&quot;9&quot; fontname=&quot;Arial&quot; color=&quot;#333333&quot; fillcolor=&quot;lightblue&quot; fixedsize=&quot;1&quot; width=&quot;1&quot;];   edge [fontsize=&quot;9&quot; fontname=&quot;Arial&quot; color=&quot;#333333&quot; arrowhead=&quot;normal&quot; arrowsize=&quot;0.5&quot;];    place_start [label=&quot;start&quot;, shape=circle, style=&quot;filled&quot;];   place_coding [label=&quot;coding&quot;, shape=circle];   place_travis [label=&quot;travis&quot;, shape=circle];   place_review [label=&quot;review&quot;, shape=circle];   place_merged [label=&quot;merged&quot;, shape=circle];   place_closed [label=&quot;closed&quot;, shape=circle];   transition_submit [label=&quot;submit&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_update [label=&quot;update&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_update [label=&quot;update&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_update [label=&quot;update&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_wait_for_review [label=&quot;wait_for_review&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_request_change [label=&quot;request_change&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_accept [label=&quot;accept&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_reject [label=&quot;reject&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   transition_reopen [label=&quot;reopen&quot;, shape=box, shape=&quot;box&quot;, regular=&quot;1&quot;];   place_start -&gt; transition_submit [style=&quot;solid&quot;];   transition_submit -&gt; place_travis [style=&quot;solid&quot;];   place_coding -&gt; transition_update [style=&quot;solid&quot;];   transition_update -&gt; place_travis [style=&quot;solid&quot;];   place_travis -&gt; transition_update [style=&quot;solid&quot;];   transition_update -&gt; place_travis [style=&quot;solid&quot;];   place_review -&gt; transition_update [style=&quot;solid&quot;];   transition_update -&gt; place_travis [style=&quot;solid&quot;];   place_travis -&gt; transition_wait_for_review [style=&quot;solid&quot;];   transition_wait_for_review -&gt; place_review [style=&quot;solid&quot;];   place_review -&gt; transition_request_change [style=&quot;solid&quot;];   transition_request_change -&gt; place_coding [style=&quot;solid&quot;];   place_review -&gt; transition_accept [style=&quot;solid&quot;];   transition_accept -&gt; place_merged [style=&quot;solid&quot;];   place_review -&gt; transition_reject [style=&quot;solid&quot;];   transition_reject -&gt; place_closed [style=&quot;solid&quot;];   place_closed -&gt; transition_reopen [style=&quot;solid&quot;];   transition_reopen -&gt; place_review [style=&quot;solid&quot;]; } <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0433\u0440\u0430\u0444 \u0432 \u0442\u0430\u043a\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043c\u043e\u0436\u043d\u043e \u043a\u0430\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PHP:  <\/p>\n<pre><code>$dumper = new \\Symfony\\Component\\Workflow\\Dumper\\GraphvizDumper(); echo $dumper-&gt;dump($stateMachine-&gt;getDefinition()); <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b  <\/p>\n<pre><code> php bin\/console workflow:dump pull_request &gt; out.dot  dot -Tpng out.dot -o graph.png <\/code><\/pre>\n<p>  graph.png \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0434 \u0434\u043b\u044f PullRequest:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/413\/9bb\/1f0\/4139bb1f0e5c4c5ab66ee153a97b1df4.png\"\/><\/p>\n<p>  \u0438 \u0434\u043b\u044f Article:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/710\/8bd\/85d\/7108bd85d85f47c98669d24c023fc6e7.png\"\/><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/325758\/\"> https:\/\/habrahabr.ru\/post\/325758\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 GitHub, \u043a\u0443\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c Pull Request. \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0442 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043d \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0438 \u043c\u0435\u0440\u0436\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. <\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d5e\/31d\/7ae\/d5e31d7ae428fc3d22a2d02226d8ad06.png\" alt=\"image\"\/><\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043f\u043e\u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u0442\u043e \u043f\u0443\u043b\u043b \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0430\u0440\u0438\u0446\u0430\u0446\u0438\u0438 \u043d\u0430\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u043b, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c \u043e WorkFlow \u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0442\u0437:<br \/>  1. \u041e\u0442\u043a\u0440\u044b\u0442<br \/>  2. \u041d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0432 Travis CI, \u043f\u0440\u0438\u0447\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0442\u0443\u0434\u0430 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c Pull Request, \u0432\u0435\u0434\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c-\u0442\u043e \u043d\u0430\u0434\u043e \u0432\u0441\u0435, \u043d\u0435 \u0442\u0430\u043a \u043b\u0438?<br \/>  3. \u0416\u0434\u0435\u0442 Review \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 Travis CI<br \/>  3.1 \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043a\u043e\u0434\u0430 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 Travis CI<br \/>  4. \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 Review<br \/>  5. \u041f\u0440\u0438\u043d\u044f\u0442 \u043f\u043e\u0441\u043b\u0435 Review<br \/>  6. \u0421\u043c\u0435\u0440\u0436\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  7. \u041e\u0442\u043a\u043b\u043e\u043d\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  8. \u0417\u0430\u043a\u0440\u044b\u0442 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d \u043f\u043e\u0441\u043b\u0435 Review<br \/>  9. \u041e\u0442\u043a\u0440\u044b\u0442 \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u0437\u0430\u043a\u0440\u044b\u0442, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043e Review<br \/>  10. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u00ab\u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\u00bb, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043e Review, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043e\u043d \u0441\u043d\u043e\u0432\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 Travis CI (\u043f\u0443\u043d\u043a\u0442 2), \u0430 \u043e\u0442 Review \u0441\u043d\u043e\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441 \u043d\u0438\u043c \u0441\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u044b\u0448\u0435  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-284572","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=284572"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284572\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=284572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=284572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=284572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}