Ошибка при сборке последней версии

Привет. При запуске ./installer rebuild web_only в последних версиях Discourse я получаю следующую ошибку:

fs.js:114
    throw err;
    ^

Error: ENOENT: no such file or directory, open 'root='/assets',url='/assets/vendor-4681e47c140b5a5bea2bfb1fec89365858288a8ea0c21979c0167ad9b570ee3d.js.map''
    at Object.openSync (fs.js:438:3)
    at Object.writeFileSync (fs.js:1189:35)
    at done (/usr/lib/node_modules/uglify-js/bin/uglifyjs:516:20)
    at cb (/usr/lib/node_modules/uglify-js/bin/uglifyjs:324:39)
    at /usr/lib/node_modules/uglify-js/bin/uglifyjs:391:9
    at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)
rake aborted!
Errno::ENOENT: No such file or directory @ rb_file_s_size - /var/www/discourse/public/assets/vendor-4681e47c140b5a5bea2bfb1fec89365858288a8ea0c21979c0167ad9b570ee3d.js
/var/www/discourse/lib/tasks/assets.rake:268:in `size'
/var/www/discourse/lib/tasks/assets.rake:268:in `block (4 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:159:in `block in concurrent?'
/var/www/discourse/lib/tasks/assets.rake:259:in `block (3 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:250:in `each'
/var/www/discourse/lib/tasks/assets.rake:250:in `block (2 levels) in <top (required)>'
/var/www/discourse/lib/tasks/assets.rake:159:in `concurrent?'
/var/www/discourse/lib/tasks/assets.rake:247:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => assets:precompile
(See full trace by running task with --trace)
I, [2019-12-11T22:53:15.806396 #18]  INFO -- : Downloading MaxMindDB...
Compressing Javascript and Generating Source Maps



FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake assets:precompile' failed with return #<Process::Status: pid 17151 exit 1>
Location of failure: /pups/lib/pups/exec_command.rb:112:in `spawn'
exec failed with the params {"cd"=>"$home", "hook"=>"assets_precompile", "cmd"=>["su discourse -c 'bundle exec rake assets:precompile'"]}
f565d457b97d7ff12a258b03a456563a5a0e928c707c70e194ef88ba170aaf3a
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one

Я отключил все плагины, но это не помогло. Не мог бы кто-нибудь пролить свет на эту проблему?

Мы уже видели это где-то раньше.

Попробуйте выполнить:

./launcher cleanup
git pull
./launcher rebuild app

Если это не поможет, удалите все контейнеры на машине и все образы.

Спасибо за быстрый ответ, @sam. Я попробую это.

Вопрос на скорую руку. Я так понимаю, что команда “git pull” загружает последнюю версию discourse-docker, верно?

В целом, необходимо ли обновлять discourse-docker и discourse одновременно?

В данный момент я не управляю discourse-docker через git. Вместо этого я загружаю конкретную ревизию discourse-docker (в виде архива Zip) при настройке сервера и фиксирую версию discourse на конкретном коммите во время развёртывания.

Я делаю это, чтобы попытаться обеспечить повторяемость сборки: запуск одной и той же команды с одинаковой конфигурацией и исходным кодом в два разных момента времени должен приводить к созданию одинакового артефакта. В целом это хорошая практика, которая уже не раз спасала меня от множества проблем с другими программами за эти годы :wink: Это даёт возможность откатиться к известной рабочей конфигурации.

Однако, кажется, что в случае с Discourse я плыву против течения, так как он, похоже, стремится загружать последние версии различных компонентов во время сборки. Я начинаю задумываться, не вредят ли мои попытки сделать сборку повторяемой самому мне?

Очень верные слова — вы попали в полностью неподдерживаемое состояние из-за этой самодеятельности :flushed_face:

Рекомендую как можно скорее обновиться до последней версии из git.

Старые Docker-образы базовой версии Discourse несовместимы с текущей версией Discourse, к тому же в них отсутствуют многие обновления безопасности.

Спасибо, @sam. Я сделал это, и теперь могу собрать новую версию. К счастью, всё это было на бета-версии, так что ничего страшного не произошло :slight_smile: Хотя я не уверен, что желание иметь повторяемую сборку можно назвать «костылями» :thinking:

Моя цель здесь — возможность отката к известной рабочей версии. Допустим, я запустил ./launcher rebuild app в момент t1, и Discourse работает. Затем я запускаю ./launcher rebuild app в момент t2, и что-то пошло не так. Как вернуть программное обеспечение к предыдущей версии? Думаю, я бы смирился с тем, что сборка не повторяема, если бы мог откатиться к известному рабочему состоянию. Поскольку запускающая программа уже создала рабочий образ Docker в момент t1, возможно ли указать ей использовать конкретный образ, а не тот, который был создан в момент t2 и оказался нерабочим?

Есть какие-то идеи?

Извините, что немного отошёл от темы. Если хотите, я могу разместить это в отдельном сообщении.

Если вы хотите получать воспроизводимые сборки, вам нужно зафиксировать версию Discourse с помощью конкретного хеша SHA в конфигурации вашего контейнера, а также для каждого плагина.

Это означает, что вы перестанете получать исправления для Discourse, обновления безопасности для образа Docker и так далее, но сборка будет довольно воспроизводимой.

Возможно, вам также потребуется внести изменения в шаблоны, чтобы зафиксировать зависимости и никогда не получать обновления безопасности для зависимостей apt.

Хорошо, я уже зафиксировал версию Discourse на конкретном коммите и могу сделать то же самое для плагинов. Но если я не зафиксировал и discourse-docker, не приведёт ли это к ситуации, где discourse-base обновляется при каждой сборке, а Discourse — нет. Не возникнет ли из-за этого аналогичная несовместимость, но в обратную сторону (потому что discourse-base будет опережать Discourse)?

Я в замешательстве: как могла появиться эта ошибка, если у вас зафиксирована старая версия Discourse?

Если в NGINX есть критическая уязвимость, вы хотите, чтобы её исправили?

Ошибка возникла, когда я перешёл от закреплённой версии Discourse 2.4.0.beta2 к версии 2.4.0beta8.

Конечно, я хотел бы, чтобы критические уязвимости в зависимых программных системах исправлялись при запуске новой сборки! Звучит отлично!

Однако я также хотел бы иметь возможность откатиться в случае, если новая версия не работает :slight_smile:

Давайте приведём конкретный пример:

Предположим, моя конфигурация находится в текущем состоянии:

discourse: 2.4.0beta2 (закреплена в web_only.yml)

Я запускаю ./launcher rebuild web_only, и всё работает.

Теперь моя система находится в следующем состоянии:

discourse: 2.4.0beta2
discourse-docker: LATEST-AT-TIME-T1

Теперь я изменяю конфигурацию на следующее состояние:

discourse: 2.4.0beta8 (закреплена в web_only.yml)

Я запускаю ./launcher rebuild web_only, и что-то ломается.

Теперь моя система находится в таком состоянии:

discourse: 2.4.0beta8
discourse-docker: LATEST-AT-TIME-T2

Теперь я хочу вернуться к предыдущей версии, чтобы всё снова заработало. Поэтому я меняю закреплённую версию Discourse на 2.4.0beta2 и запускаю сборку заново. Однако при запуске ./launcher rebuild web_only система оказывается в следующем состоянии:

discourse: 2.4.0beta2
discourse-docker: LATEST-AT-TIME-T2

Хотя закреплённая версия Discourse та же самая, версия discourse-base (и остальной части discourse-docker, шаблонов, самого ./launcher и т. д.) теперь будет другой, поэтому я не возвращаюсь к известному рабочему состоянию, и меня беспокоит, что сборка вообще не завершится.

Извините, если я кажусь тупым, я просто хочу иметь возможность вернуться к безопасному состоянию в случае проблем во время обновления. Возможно, повторный запуск ./launcher rebuild web_only — это просто неправильный способ отката? Для других систем, которые я разворачиваю, я бы просто развернул предыдущий образ Docker. Есть ли способ указать launcher сделать это?

Да, вам нужно пересмотреть свой процесс. Наши миграции базы данных необратимы. Если вы хотите протестировать обновление без его применения, вам нужно работать в тестовой среде (staging sandbox).

Да, я понимаю, что откат миграции базы данных — задача не из легких. Очевидно, что Discourse не создавался с учётом моей стратегии управления выпусками и развёртыванием. Мне стоит перестать плыть против течения.

У меня есть тестовое окружение. Поэтому я просто откажусь от любых идей повторного создания сборок и автоматического развёртывания: буду тестировать на staging, а при переходе на production — надеяться на лучшее.

Спасибо за помощь, @sam.