有一个生产系统已运行多年,首先作为PHP应用程序,然后作为Rails的混合,现在完全在Rails中。目前还不清楚它已经存在了多长时间。最古老的git提交是从5年前开始的。
目标是不惜一切代价保持系统运行。只要没有任何破坏,我们使用什么代码并不重要。目前它位于Rails版本3.2.33
。
如果我们不升级任何宝石,我们就有可能变得过时和不可部署。如果我们升级,我们将需要对代码进行更改,从而导致潜在的错误蔓延。不仅因为AWS中断而导致代码损坏,还会导致停机。
确保没有任何损失的第一步是什么?我花了几个月写黄瓜(整合)测试,但很难涵盖每个边缘情况。该应用程序已经运行了很长时间,大多数错误已得到修复,几乎没有新的例外。测试从一开始就不是优先考虑因素,因此大部分代码都没有记录。
答案 0 :(得分:4)
老实说,我发现Ruby on Rails并不适合这种应用程序。 Ruby和Rails都有非常激进的发布时间表,Rails特别不怕放弃向后兼容性。 Rails非常适合敏捷开发,因为事情总是在变化,但代价是长期稳定。
我假设你的应用程序足够大,你不想切换到其他任何东西。例如,Sinatra并没有太大变化,而且是一个更稳定的选择。
如果您坚持使用Rails,我建议尽可能多地删除gem依赖项。它们总是存在着不再被开发或者它们可能引入漏洞或漏洞的危险。
此外,尽可能地优先考虑PORO(普通的旧Ruby对象)而不是Rails依赖代码。它通常需要更多的工作,但你最终得到更稳定和可重用的代码。
我意识到这可能比你想要放入这样的应用程序更多的工作,但这是我最好的建议。
答案 1 :(得分:1)
第一步是为gem文件中使用的所有gem设置特定的gem版本。
例如
gem 'rspec-rails'
可能会成为
gem 'rspec-rails', '2.14.1'
您可以通过查看Gemfile.lock来确定当前使用的版本,例如,Gemfile.lock中的这一行显示为rspec选择的版本:
rspec (2.14.1)
即使Gemfile没有版本,例如
gem chronic
Gemfile 将具有使用的版本,例如
chronic (0.10.2)
如果我们不升级任何宝石,我们就有可能变得过时和不可部署。如果我们升级,我们将需要对代码进行更改,从而导致潜在的错误蔓延。
是的,那是你的困境。没有任何魔力,您必须选择要解决的这两个优先级中的哪一个。正如aNoble所说,RoR不是一个可以“留在原地”的框架。结合在一起构成大多数应用程序的宝石的不断变化意味着RoR应用程序不能很好地老化。
您应该向项目所有者解释并重复,重复,重复此操作。通常这是一种“被接受”的原则 - 但不是真的 - 因为同样的问题继续被问到“尽管如此,我怎样才能升级它,我怎样才能确保没有任何变化或破坏等等。”
如果申请将在几个月内退役,没问题。如果没有真正的计划来落实应用程序,它将继续成为业务的重要组成部分,那么您只需要使用资源来维护它。在RoR土地上没有免费午餐。
答案 2 :(得分:1)
写出许多测试是关键的第一步,很高兴看到这一点。检查您的声明范围,看看您是否缺少重要代码区域的测试,并确保您具有涵盖关键序列的集成测试。我们的想法是修改您的测试,以降低更改导致用户可见故障的风险。
现在在某个系统上设置连续测试。
设置您的Gemfile和.ruby-version,以便您可以精确控制所有内容的加载版本。这不会自动更新 - 但它可确保您对更新内容进行控制。检查Gemfile和Gemfile.lock。
此时您可以慢慢地增加版本号。不要跳过很多版本号 - 通常情况下升级速度较慢,以便您可以看到弃用警告。修复,冲洗,重复。
将您的(输入)验证器修改为挑剔的白名单("它必须是这种形式,否则我不会接受它")。如果您可以阻止进入系统中的错误数据,那么它更有可能正常工作,并且通常会更难攻击。
为了安全起见,请考虑添加安全标头,并将CSP设置为尽可能强大。
开始添加一些静态分析仪。 Rubocop和Brakeman非常有用。您可能必须将Rubocop配置为只抱怨一些事情,然后慢慢增加他们报告的内容。将所有支票添加到默认" rake"命令,这样你就可以输入" rake"运行静态分析器和测试套件。
无论你使用什么框架,都没有魔力。人们犯错误,假装其他方面没有帮助。
CII Best Practices badge project可能是一个有用的例子。它使用RoR,我领导它。特别是,请参阅: * CONTRIBUTING * Security information (assurance case)
来自贡献: "一般而言,我们会尽快主动发现并消除错误和漏洞,并在发生错误和漏洞时减少其影响。我们使用防御设计和编码风格来减少错误的可能性,各种试图尽早发现错误的工具,以及具有重要覆盖范围的自动测试套件。"