尝试运行 poll 插件的 specs 时出现“不存在名为 __ 的设置”

你好,

我正在开发一个插件,并尝试编写一些测试。但是,当我尝试通过以下命令运行 poll 插件的测试规范时:

bundle exec rake plugin:spec poll

此处 所示,我遇到了以下错误:

加载 ./plugins/poll/spec/integration/poll_endpoints_spec.rb 时发生错误。
失败原因:raise ArgumentError.new(“No setting named ‘#{name}’ exists”)

ArgumentError:
  不存在名为 'discourse_narrative_bot_enabled' 的设置
# ./lib/site_settings/defaults_provider.rb:58:in `set_regardless_of_locale'
# ./config/environments/test.rb:74:in `block (3 levels) in <main>'
# ./config/environments/test.rb:63:in `tap'
# ./config/environments/test.rb:63:in `block (2 levels) in <main>'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:68:in `block in execute_hook'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:61:in `with_execution_control'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:66:in `execute_hook'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:52:in `block in run_load_hooks'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:51:in `each'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/activesupport-6.1.3.2/lib/active_support/lazy_load_hooks.rb:51:in `run_load_hooks'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/application/finisher.rb:140:in `block in <module:Finisher>'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:32:in `instance_exec'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:32:in `run'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:61:in `block in run_initializers'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:60:in `run_initializers'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/application.rb:384:in `initialize!'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/railtie.rb:207:in `public_send'
# /Users/myUser/.rvm/gems/ruby-2.7.0/gems/railties-6.1.3.2/lib/rails/railtie.rb:207:in `method_missing'
# ./config/environment.rb:7:in `<top (required)>'
# ./spec/rails_helper.rb:56:in `require'
# ./spec/rails_helper.rb:56:in `<top (required)>'
# ./plugins/poll/spec/integration/poll_endpoints_spec.rb:3:in `require'
# ./plugins/poll/spec/integration/poll_endpoints_spec.rb:3:in `<top (required)>'

我在尝试运行 poll 插件的测试时做错了什么?为什么这个特定的设置没有加载到默认区域设置中?

谢谢。

若要仅运行 poll 相关的测试,请使用命令:bundle exec rake "plugin:spec[poll]"(或更简短的:bin/rake "plugin:spec[poll]"),否则将会运行所有插件的测试。

关于你遇到的错误,我不太确定。测试数据库是否已迁移?(bin/rails db:migrate RAILS_ENV=test

谢谢。正如你所说,它确实运行了所有插件的规范测试,我通过移除其他插件解决了这个问题。我是基于这篇帖子进行的,但原来括号的位置放错了。

是的,测试环境中的数据库已经迁移。我通过注释掉 raise ArgumentError.new("No setting named '#{name}' exists") 这一行并用 puts 替换它来绕过这个错误,结果显示只有 discourse_narrative_bot_enabled 会触发此错误;其他所有设置都正常。我认为我们并没有对这个设置做过任何操作。无论如何,既然我的规范测试在忽略此错误的情况下能够正常运行,我可以将这一临时解决方案保留在本地 Discourse 中。等我找到真正的原因后,我会更新这篇帖子。

我目前在 CI 中运行数据库迁移时遇到此确切错误:

Run bin/rake db:create
rake aborted!
ArgumentError: No setting named 'discourse_narrative_bot_enabled' exists
/home/runner/work/discourse-multilingual/discourse-multilingual/lib/site_settings/defaults_provider.rb:58:in `set_regardless_of_locale'
/home/runner/work/discourse-multilingual/discourse-multilingual/config/environments/test.rb:73:in `block (3 levels) in <main>'
/home/runner/work/discourse-multilingual/discourse-multilingual/config/environments/test.rb:63:in `tap'
/home/runner/work/discourse-multilingual/discourse-multilingual/config/environments/test.rb:63:in `block (2 levels) in <main>'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:79:in `block in execute_hook'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:72:in `with_execution_control'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:77:in `execute_hook'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:63:in `block in run_load_hooks'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:62:in `each'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/lazy_load_hooks.rb:62:in `run_load_hooks'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/application/finisher.rb:87:in `block in <module:Finisher>'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/initializable.rb:32:in `instance_exec'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/initializable.rb:32:in `run'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/initializable.rb:60:in `run_initializers'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/application.rb:372:in `initialize!'
/home/runner/work/discourse-multilingual/discourse-multilingual/config/environment.rb:7:in `<main>'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.6.0/lib/zeitwerk/kernel.rb:35:in `require'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/application.rb:348:in `require_environment!'
/home/runner/work/discourse-multilingual/discourse-multilingual/vendor/bundle/ruby/2.7.0/gems/railties-7.0.3.1/lib/rails/application.rb:511:in `block in run_tasks_blocks'
Tasks: TOP => db:migrate => db:load_config => environment
(See full trace by running task with --trace)
Error: Process completed with exit code 1.

似乎是由核心中的这一行引起的:

团队,这快把我逼疯了。

我们的 CIdb:migrate 时因为这个而中断。

这几乎是逐字复制了 discourse-chat 插件的 CI,只是增加了一个 cron 计划。

我们的 CI 对 PR 和提交有效,但在 cron 作业时每次都会在这里失败。

我可以在 rails 控制台中通过类似的块重现此问题:

[19] pry(main)> SiteSetting.defaults.tap do |s|
[19] pry(main)*   s.set_regardless_of_locale(:discourse_narrative_bot_enab, false)
[19] pry(main)* end
ArgumentError: No setting named 'discourse_narrative_bot_enab' exists

如果我这样做,它就能工作:

[21] pry(main)> SiteSetting.defaults.tap do |s|
[21] pry(main)*   if s.has_setting? :discourse_narrative_bot_enab
[21] pry(main)*     s.set_regardless_of_locale(:discourse_narrative_bot_enab, false)
[21] pry(main)*   end
[21] pry(main)* end

只是为了检查一下,它会失败:

[21] pry(main)> SiteSetting.defaults.tap do |s|
[21] pry(main)*   if s.has_setting? :discourse_narrative_bot_enabled
[21] pry(main)*     s.set_regardless_of_locale(:discourse_narrative_bot_enab, false)
[21] pry(main)*   end
[21] pry(main)* end

所以我建议在 PR 中进行以下更改,我很乐意提交:

 if ENV['LOAD_PLUGINS'] == '1' && s.has_setting? :discourse_narrative_bot_enabled

出于某种原因,无法保证叙述机器人插件的存在?

在这些示例中,您的站点设置是 discourse_narrative_bot_enab,而不是 discourse_narrative_bot_enabled。我猜一旦纠正了这一点,它就无法重现了?

最令人惊讶的是:

这表明计划运行的运行时环境存在差异 :thinking:

查看其中一个失败的日志,似乎 GitHub 将 multilingual 插件直接克隆到了 plugins 目录中,而不是它自己的目录中。因此,它基本上“卸载”了所有核心插件(并且未能正确安装自身)。

我怀疑,为了让 cron 生效,我们需要将 github.event.repository.name 的所有出现替换为其他内容:

https://github.com/paviliondev/discourse-multilingual/blob/main/.github/workflows/plugin-tests.yml#L40

查看文档,似乎没有一致的方法来获取存储库名称(不带所有者),因此我们需要一些技巧。我认为这应该可以做到:

抄送 @cvx - 也许我们应该在插件/主题模板 CI 中使用这种技术?

这是故意设置为强制出错(并进行处理)的。

哦天哪,抓得好,谢谢!

已合并,非常感谢您 @David,您真是太好了。

如果我到您那里,我请您喝啤酒! :slight_smile:

顺便说一下,cron 测试刚刚完美运行,再次感谢!:tada:

@cvx 刚和我分享了这篇文章:

所以,对于 cron 作业,不再需要 hacky 的仓库名称的变通方法了 :tada: @merefield