13

我目前正在为一个慈善组织开发一个 php 应用程序,我现在正处于定义部署实践的阶段。

我们的应用程序同时使用 Zend Framework 和 Doctrine。应用程序将部署到不同的服务器,每个服务器都有不同的配置文件。这些机器都是 Windows 和 Linux(但都使用 Apache 和 php 5.2+)。

源代码在 subversion 存储库中可用,我们希望在 Linux 服务器上构建和存储我们的包。

最好我们希望更新过程像在应用程序目录中运行更新命令一样简单,其中更新命令还更新数据库(使用教义脚本)并确保框架的依赖关系。此更新命令必须是机器上的命令(我们不能 ssh 进入它们)。最好我们可以选择下载新版本或为已下载的 tarball 提供新版本。(但只下载或只 tarball 也可以)

带有安装和更新(新版本)的软件包也最好由单个命令构建。

我一直在阅读有关 phar、pear、phing 的一些信息,但我不知道最好的方法是什么。持续集成服务器并不是真正需要的,但我考虑在构建版本后自动部署测试环境。

最初只有 php 应用程序的更新必须非常容易,安装时可以手动填写最初的配置文件。

4

6 回答 6

3

我首先将各种服务器的应用程序根设为 SVN 工作副本。您可以添加 mod_rewrite(或 IIS 的 IIRF ASAPI 过滤器)规则,以确保人们无法直接处理您的 .svn 目录。

然后,更新到最新的源可以像更新 SVN 一样简单。对于您的数据库更新需求,我也会在 SVN 中维护数据库修改脚本。您可能需要将 SVN 更新包装在批处理/shell 脚本中,以便在下载脚本后执行数据库更新。

对于实时服务器上的变更管理,我也有他们的工作副本,而不是主干,而是一个发布分支。当您准备好发布时,您可以将主干合并到发布分支中。这将允许您在实时服务器上执行部署之前测试部署并确保它是可靠的。它还具有很好的副作用,即为您提供站点发布版本的精美副本,以防您需要在发布后追踪问题。

最后,根据这些更新的强度和时间,您可能还希望更新脚本翻转“维护中”开关,以便用户暂时收到正确的消息而不是损坏的站点。

于 2010-01-06T01:01:15.257 回答
2

Benjamin Eberlei 几周前发布了一篇博客,标题为尝试使用两步 PEAR/PHAR 方法进行开发和部署。他描述了一个非常有趣且优雅的部署 PHP 应用程序的过程。

于 2010-01-06T03:49:36.717 回答
1

我使用 subversion 作为部署工具,效果很好。

在所有生产服务器上使用 svn update,或使用 phing。(或者甚至使用 phing 来 svn 更新。)

使回滚和备份变得轻而易举。请记住删除对任何 .svn 目录的访问权限。

于 2010-01-06T04:11:50.590 回答
1

无论哪种方式,我都会用 phing 或类似的东西来管理你的构建。让它运行你的测试、生成文档、构建和发布你的包/压缩包。

至于分发,您可以运行自己的 PEAR 服务器。这里的基本原理是您说您希望用户提取更新,您同时拥有 Windows 和 Linux 用户,并且您希望为他们处理依赖关系。PEAR 应该能够用一个命令来处理所有这些。

也就是说,我会选择最简单的适合你的用户的东西。这可能只是一个可通过 HTTP 获得的 tarball 和一个小型 PHP 升级脚本(或 phing 目标。)

绝对提供一种简单的方法来回滚到以前的版本。使用代码/配置,您可以保留一份副本。使用 DB,使用迁移(听起来你已经在这样做了。)

于 2010-01-06T04:16:52.250 回答
0

也许有时更简单的方法效果最好。如果您在 svn 存储库中简单地标记了稳定版本,那么您只需编写一个批处理 / bash 脚本来下载最新版本,同时在无需用户干预的情况下备份到旧版本 - 您也可以以这种方式运行所需的任何脚本。另一种选择是在 PHP 中为此编写一个简单的接口,但这取决于它需要多么简单。

于 2010-01-06T00:18:32.367 回答
0

你说你有一个claster。我们处于相同的位置,我们使用 ZF 和 Doctrine。这就是我们解决问题的方法:

<?xml version="1.0" encoding="UTF-8"?>
<project name="yourprojectname" basedir=".">

<target name="deploy" depends="apply-deltas,update-app01,update-app02">

</target>

<target name="update-app01">

  <sshexec host="app01"
    username="yourusername"
    password="yourpassword"
    trust="true"
    command="cd path/to/root/directory &amp;&amp;
      svn update &amp;&amp;
      php cmd/clear_cache.php
      "/>

</target>

<target name="update-app02">

  <sshexec host="app02"
      username="yourusername"
      password="yourpassword"
      trust="true"
      command="cd path/to/root/directory &amp;&amp;
      svn update &amp;&amp;
      php cmd/clear_cache.php
      "/>

</target>

  <target name="apply-deltas" depends="liquibase-prepare">
     <updateDatabase
          changeLogFile="${db.changelog.file}"
          driver="${database.driver}"
          url="${database.url}"
          username="${database.username}"
          password="${database.password}"
          promptOnNonLocalDatabase="${prompt.user.if.not.local.database}"
          dropFirst="false"
          classpathref="classpath" >
          <changeLogProperty name="table.name" value="ant_param_table"/>
     </updateDatabase>
  </target>


<target name="liquibase-prepare">
    <path id="classpath">
    <fileset dir="${basedir}/libNoPackage">
        <include name="**/*.jar" />
    </fileset>
    </path>

    <taskdef resource="liquibasetasks.properties">
        <classpath refid="classpath"/>
    </taskdef>
  </target>

</project>

这远非理想,但对我们来说效果很好。希望有帮助。

链接:

阿帕奇蚂蚁

LiquiBase

如果您有任何问题,请告诉我,以便我更新答案。t

于 2010-01-05T14:29:20.410 回答