Регрессия shallow git fetch в discourse_docker

Здравствуйте,

Недавний коммит в docker_discourse https://github.com/discourse/discourse_docker/commit/e2eb085714dfcf2aa0117b0f2fdf39b762b0e18d нарушает возможность указания тега (например, v2.6.0) в значении version: файла app.yml. Это полезно для установки старых версий Discourse в тестовых целях.

Проблема проявляется следующим образом при указании version: v2.6.0 с использованием коммита e2eb085714dfcf2aa0117b0f2fdf39b762b0e18d:

I, [2020-12-05T10:59:38.848743 #1]  INFO -- : > cd /var/www/discourse && git remote set-branches origin v2.6.0
I, [2020-12-05T10:59:38.852600 #1]  INFO -- : 
I, [2020-12-05T10:59:38.852639 #1]  INFO -- : > cd /var/www/discourse && git fetch --depth 1 origin v2.6.0
From https://github.com/discourse/discourse
 * tag                 v2.6.0     -> FETCH_HEAD
I, [2020-12-05T10:59:41.405163 #1]  INFO -- : 
I, [2020-12-05T10:59:41.405307 #1]  INFO -- : > cd /var/www/discourse && git checkout v2.6.0
error: pathspec 'v2.6.0' did not match any file(s) known to git
I, [2020-12-05T10:59:41.411796 #1]  INFO -- : 

Вместо ожидаемого вывода, который был при использовании коммита, предшествующего указанному выше:

I, [2020-12-05T11:22:14.717910 #1]  INFO -- : > cd /var/www/discourse && git fetch origin v2.6.0
From https://github.com/discourse/discourse
 * tag                     v2.6.0     -> FETCH_HEAD
I, [2020-12-05T11:22:15.672616 #1]  INFO -- : 
I, [2020-12-05T11:22:15.672683 #1]  INFO -- : > cd /var/www/discourse && git checkout v2.6.0
Note: checking out 'v2.6.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at d6121249d3 Version bump to v2.6.0

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

@Falco расследует.

Я согласен, что глубину следует сделать настраиваемой, возможно, через переменную окружения, по умолчанию «shallow», но с возможностью настройки через простую переменную окружения.

Я думаю, что проблема здесь в том, что теги неизвестны локально при выполнении checkout, как в следующем (не связанном с Discourse) вопросе:

Выполнение git fetch --all должно решить проблему, но я не знаю, насколько это увеличит размер образа (если только другая инструкция позже не очистит неиспользуемые ссылки).

Тем не менее, я считаю, что git clone --depth 1 https://github.com/discourse/discourse.git --branch=$version решит это, поскольку параметр branch поддерживает как ветки, так и теги, но я не тестировал это и не знаю, есть ли причина, по которой клонирование использует (в настоящее время) ветку master.

При выполнении git clone --depth 1 https://github.com/discourse/discourse.git --branch=v2.6.0 размер всей папки составляет 212 МБ, а папка .git внутри — 46 МБ, так что, думаю, это приемлемо.

Это удваивает размер репозитория :slightly_frowning_face:

Проблема в том, что на момент сборки образа я не знаю, какую ветку вы захотите использовать в будущем.

Текущая настройка была изменена для уменьшения размера образа, что позволило сократить его сжатый размер на 250 МБ (25%), что является огромным преимуществом. Это работает отлично при использовании обычных веток, таких как stable и beta или tests-passed.

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

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
+    - exec:
+        cd: $home
+        cmd:
+          - git fetch --depth=1 origin tag v2.5.0 --no-tags
+          - git checkout v2.5.0

Другим обходным решением является добавление ключа base_image на верхний уровень файла app.yml со значением старого базового образа. Поскольку мы даже не пытаемся поддерживать совместимость новых образов с запуском старых версий Discourse, это может быть необходимо, если вы возвращаетесь к очень старым версиям.

Вы правы, в тот момент мы не знаем версию. Похоже, базовый образ использует текущую версию + ветку tests-passed, хотя в ветке будет тот коммит, который был на момент сборки образа.

Не приводит ли текущий подход к более медленным пересборкам, даже при использовании ветки tests-passed?

Просто рассмотрите следующие инструкции:

В базовом образе:

git clone --depth 1 https://github.com/discourse/discourse.git
cd discourse/
git remote set-branches --add origin tests-passed

В web.template.yml

git reset --hard
git clean -f
git remote set-branches --add origin master
git pull
...
Когда вызывается `git pull`, **извлекается весь репозиторий**, и это может занять несколько минут, так как ранее было выполнено только частичное клонирование. Вы можете попробовать выполнить только указанные выше инструкции локально и проверить. Я не утверждаю, что наличие всего репозитория в базовом образе лучше, но код в `web.template.yml` будет выполняться при каждой пересборке, даже если был добавлен только плагин или изменена настройка в `app.yml`. Обычно в моих проектах (не связанных с Discourse) я создаю новый образ для каждой новой версии, но для вас это может быть нецелесообразно (учитывая ваш текущий подход). Вы не замечали увеличения времени пересборки? (Или, возможно, это не так значительно по сравнению с общим временем пересборки в большинстве случаев?)

Обновление

Я снова протестировал описанные выше шаги, и они оказались быстрыми. Похоже, при первой попытке я выполнил другую команду, которая изменила дерево git, и в итоге при запуске git pull попыталось извлечь всё.

Вы уверены в этом?

➜  discoursesmall git:(6a42acbf) docker run --rm -it discourse/base:2.0.20201125-2246
root@b481d11669ba:/# cd /var/www/discourse/
root@b481d11669ba:/var/www/discourse# du -sh .                                                     
774M    . 
root@b481d11669ba:/var/www/discourse# git pull
...
root@b481d11669ba:/var/www/discourse# du -sh .                                                                
778M    . 

@lucasbasquerotto вы правы, указывая на то, что git pull строго не обязателен, мы убрали его здесь

Это должно позволить другим веткам (или форкам) работать с discourse_docker чуть более гладко в дальнейшем :slight_smile:

Да, я вижу, что после pull выполняется fetch и затем checkout в правильной ветке, поэтому, думаю, git pull не нужен (хотя я это не проверял).

Что касается тегов, похоже, что их всё ещё нужно подтягивать отдельно, но это вполне осуществимо. Кроме того, ветки используются чаще, поэтому теги, вероятно, будут скорее исключением из правила.

Можно ли считать, что опция версии в файле конфигурации standalone.yml не имеет эффекта?

Это всё ещё имеет эффект, но теперь его можно устанавливать только для веток.

У меня возникает та же ошибка. Я использовал версию 2.5.1.

После этого я получаю следующую ошибку:

I, [2020-12-31T11:50:24.701475 #1]  INFO -- : > cd /var/www/discourse && find /var/www/discourse ! -user discourse -exec chown discourse {} \+
chown: не удалось разыменовать '/var/www/discourse/public/plugins/styleguide': файл или каталог не существует

Пересборка не работает. Любая помощь?

Попробуйте добавить указанный ключ и использовать более старый образ из discourse/base - Docker Image

Это не работает, потому что выполняется после кода, который не может получить версию и завершается ошибкой. Рабочим решением оказалось создание файла version.template.yml рядом с web.template.yml со следующим содержимым:

params:
  home: /var/www/discourse

run:
  - exec:
      cd: $home
      hook: code
      cmd:
        - git fetch --tags

Затем включите этот файл в containers/app.yml перед web.template.yml следующим образом:

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/version.template.yml"
  - "templates/web.template.yml"

Чтобы это сработало, не используйте ключ верхнего уровня version в вашем файле app.yml, только этот новый код. В этом случае ошибка не возникнет.

Спасибо за уточнение: это именно та часть, которой мне не хватало. Для тех, кто запутался так же, как и я, получение релизного тега Discourse можно выполнить следующим образом:

  • Убедитесь, что параметр version не задан в app.yml, например:
    params:
      db_default_text_search_config: "pg_catalog.english"
      #  version: stable
    
  • Добавьте код для перехода на нужную версию в конце файла app.yml, например:
    hooks:
      after_code:
        - exec:
            cd: $home/plugins
            cmd:
              - git clone https://github.com/discourse/docker_manager.git
    +    - exec:
    +        cd: $home
    +        cmd:
    +          - git fetch --depth=1 origin tag v2.5.0 --no-tags
    +          - git checkout v2.5.0
    

При запуске ./launcher rebuild app происходит следующее:

  • По умолчанию переходится на ветку version (т. е. ветку test_passed).
  • Затем загружается и переходит на тег v2.5.0, что фактически заменяет предыдущую версию.