From f55b0ca7973ec7ca2ce02eb87831385d4c39bd22 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Thu, 25 Sep 2025 19:10:46 +0200 Subject: [PATCH] web-app-openproject: migrate from OpenProject 13 to 14 - updated base image from openproject/community:13 to openproject/openproject:14 - added dedicated migration task (db:migrate + schema cache clear) - moved settings, ldap, and admin tasks to separate files - adjusted docker-compose template to use OPENPROJECT_WEB_SERVICE / OPENPROJECT_SEEDER_SERVICE variables - replaced postinstall.sh with precompile-assets.sh - ensured depends_on uses variable-based service names Ref: https://chatgpt.com/share/68d57770-2430-800f-ae53-e7eda6993a8d --- roles/web-app-openproject/config/main.yml | 4 ++-- .../tasks/01_migration.yml | 16 ++++++++++++++ .../web-app-openproject/tasks/02_settings.yml | 10 +++++++++ .../tasks/{01_ldap.yml => 03_ldap.yml} | 0 .../tasks/{02_admin.yml => 04_admin.yml} | 0 roles/web-app-openproject/tasks/main.yml | 21 +++++++------------ .../templates/Dockerfile.j2 | 2 +- .../templates/docker-compose.yml.j2 | 18 ++++++++-------- roles/web-app-openproject/vars/main.yml | 6 ++++-- 9 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 roles/web-app-openproject/tasks/01_migration.yml create mode 100644 roles/web-app-openproject/tasks/02_settings.yml rename roles/web-app-openproject/tasks/{01_ldap.yml => 03_ldap.yml} (100%) rename roles/web-app-openproject/tasks/{02_admin.yml => 04_admin.yml} (100%) diff --git a/roles/web-app-openproject/config/main.yml b/roles/web-app-openproject/config/main.yml index 2415f69f..03204a4d 100644 --- a/roles/web-app-openproject/config/main.yml +++ b/roles/web-app-openproject/config/main.yml @@ -38,8 +38,8 @@ docker: enabled: true web: name: openproject-web - image: openproject/community - version: "13" # Update when available. No rolling release implemented + image: openproject/openproject + version: "14" # Update when available. No rolling release implemented backup: no_stop_required: true cpus: "3.0" diff --git a/roles/web-app-openproject/tasks/01_migration.yml b/roles/web-app-openproject/tasks/01_migration.yml new file mode 100644 index 00000000..be580ccc --- /dev/null +++ b/roles/web-app-openproject/tasks/01_migration.yml @@ -0,0 +1,16 @@ +- name: Run DB migrations (OpenProject) + shell: > + docker compose run --rm {{ OPENPROJECT_SEEDER_SERVICE }} bash -lc + "cd /app && RAILS_ENV={{ ENVIRONMENT | lower }} bin/rails db:migrate" + args: + chdir: "{{ docker_compose.directories.instance }}" + register: openproject_migrate + changed_when: openproject_migrate.rc == 0 + failed_when: openproject_migrate.rc != 0 + +- name: Clear schema cache + shell: > + docker compose run --rm {{ OPENPROJECT_SEEDER_SERVICE }} bash -lc + "cd /app && RAILS_ENV={{ ENVIRONMENT | lower }} bin/rails db:schema:cache:clear" + args: + chdir: "{{ docker_compose.directories.instance }}" \ No newline at end of file diff --git a/roles/web-app-openproject/tasks/02_settings.yml b/roles/web-app-openproject/tasks/02_settings.yml new file mode 100644 index 00000000..ce61137d --- /dev/null +++ b/roles/web-app-openproject/tasks/02_settings.yml @@ -0,0 +1,10 @@ +- name: Set settings in OpenProject + shell: > + docker compose exec {{ OPENPROJECT_WEB_SERVICE }} bash -c "cd /app && + RAILS_ENV={{ ENVIRONMENT | lower }} bundle exec rails runner \"Setting[:{{ item.key }}] = '{{ item.value }}'\"" + args: + chdir: "{{ docker_compose.directories.instance }}" + loop: "{{ OPENPROJECT_RAILS_SETTINGS | dict2items }}" + async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" + poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" + no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" diff --git a/roles/web-app-openproject/tasks/01_ldap.yml b/roles/web-app-openproject/tasks/03_ldap.yml similarity index 100% rename from roles/web-app-openproject/tasks/01_ldap.yml rename to roles/web-app-openproject/tasks/03_ldap.yml diff --git a/roles/web-app-openproject/tasks/02_admin.yml b/roles/web-app-openproject/tasks/04_admin.yml similarity index 100% rename from roles/web-app-openproject/tasks/02_admin.yml rename to roles/web-app-openproject/tasks/04_admin.yml diff --git a/roles/web-app-openproject/tasks/main.yml b/roles/web-app-openproject/tasks/main.yml index 614ff4a9..dcef15c3 100644 --- a/roles/web-app-openproject/tasks/main.yml +++ b/roles/web-app-openproject/tasks/main.yml @@ -12,7 +12,7 @@ - name: "Transfering Gemfile.plugins to {{ OPENPROJECT_PLUGINS_FOLDER }}" copy: src: Gemfile.plugins - dest: "{{ OPENPROJECT_PLUGINS_FOLDER }}Gemfile.plugins" + dest: "{{ [OPENPROJECT_PLUGINS_FOLDER,'Gemfile.plugins'] | path_join }}" notify: - docker compose up - docker compose build @@ -26,20 +26,15 @@ - name: flush docker service meta: flush_handlers -- name: Set settings in OpenProject - shell: > - docker compose exec web bash -c "cd /app && - RAILS_ENV={{ ENVIRONMENT | lower }} bundle exec rails runner \"Setting[:{{ item.key }}] = '{{ item.value }}'\"" - args: - chdir: "{{ docker_compose.directories.instance }}" - loop: "{{ OPENPROJECT_RAILS_SETTINGS | dict2items }}" - async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" - poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" - no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" +- name: Execute Migrations + include_tasks: 01_migration.yml + +- name: Deploy Settings + include_tasks: 02_settings.yml - name: Setup LDAP - include_tasks: 01_ldap.yml + include_tasks: 03_ldap.yml when: OPENPROJECT_LDAP_ENABLED | bool - name: Create OpenProject Administrator - include_tasks: 02_admin.yml \ No newline at end of file + include_tasks: 04_admin.yml \ No newline at end of file diff --git a/roles/web-app-openproject/templates/Dockerfile.j2 b/roles/web-app-openproject/templates/Dockerfile.j2 index d82396b4..2044ccf3 100644 --- a/roles/web-app-openproject/templates/Dockerfile.j2 +++ b/roles/web-app-openproject/templates/Dockerfile.j2 @@ -11,4 +11,4 @@ COPY volumes/plugins/Gemfile.plugins /app/ # RUN npm add npm * RUN bundle config unset deployment && bundle install && bundle config set deployment 'true' -RUN ./docker/prod/setup/postinstall.sh \ No newline at end of file +RUN ./docker/prod/setup/precompile-assets.sh \ No newline at end of file diff --git a/roles/web-app-openproject/templates/docker-compose.yml.j2 b/roles/web-app-openproject/templates/docker-compose.yml.j2 index 54bbb0f4..787499df 100644 --- a/roles/web-app-openproject/templates/docker-compose.yml.j2 +++ b/roles/web-app-openproject/templates/docker-compose.yml.j2 @@ -23,16 +23,16 @@ x-op-app: &app ports: - "127.0.0.1:{{ ports.localhost.http[application_id] }}:80" environment: - APP_HOST: web + APP_HOST: {{ OPENPROJECT_WEB_SERVICE }} depends_on: - - web + - {{ OPENPROJECT_WEB_SERVICE }} volumes: - "data:/var/openproject/assets" - "{{ OPENPROJECT_DUMMY_VOLUME }}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes - web: + {{ OPENPROJECT_WEB_SERVICE }}: <<: *app -{% set service_name = 'web' %} +{% set service_name = OPENPROJECT_WEB_SERVICE %} {% include 'roles/docker-container/templates/base.yml.j2' %} command: "./docker/prod/web" container_name: {{ OPENPROJECT_WEB_CONTAINER }} @@ -40,7 +40,7 @@ x-op-app: &app {% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %} cache: condition: service_started - seeder: + {{ OPENPROJECT_SEEDER_SERVICE }}: condition: service_started {% set container_port = 8080 %} {% set container_healthcheck = 'health_checks/default' %} @@ -59,7 +59,7 @@ x-op-app: &app {% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %} cache: condition: service_started - seeder: + {{ OPENPROJECT_SEEDER_SERVICE }}: condition: service_started volumes: - "data:/var/openproject/assets" @@ -75,15 +75,15 @@ x-op-app: &app {% include 'roles/docker-container/templates/depends_on/dmbs_incl.yml.j2' %} cache: condition: service_started - seeder: + {{ OPENPROJECT_SEEDER_SERVICE }}: condition: service_started volumes: - "data:/var/openproject/assets" - "{{ OPENPROJECT_DUMMY_VOLUME }}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes - seeder: + {{ OPENPROJECT_SEEDER_SERVICE }}: <<: *app -{% set service_name = 'seeder' %} +{% set service_name = OPENPROJECT_SEEDER_SERVICE %} {% set docker_restart_policy = 'on-failure' %} {% include 'roles/docker-container/templates/base.yml.j2' %} command: "./docker/prod/seeder" diff --git a/roles/web-app-openproject/vars/main.yml b/roles/web-app-openproject/vars/main.yml index ea0549c5..f166840a 100644 --- a/roles/web-app-openproject/vars/main.yml +++ b/roles/web-app-openproject/vars/main.yml @@ -14,8 +14,10 @@ docker_compose_flush_handlers: false OPENPROJECT_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.web.version') }}" OPENPROJECT_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.web.image') }}" OPENPROJECT_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}" -OPENPROJECT_WEB_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.web.name') }}" -OPENPROJECT_SEEDER_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.seeder.name') }}" +OPENPROJECT_WEB_SERVICE: "web" +OPENPROJECT_WEB_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.' ~ OPENPROJECT_WEB_SERVICE ~ '.name') }}" +OPENPROJECT_SEEDER_SERVICE: "seeder" +OPENPROJECT_SEEDER_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.' ~ OPENPROJECT_SEEDER_SERVICE ~ '.name') }}" OPENPROJECT_CRON_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.cron.name') }}" OPENPROJECT_PROXY_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.proxy.name') }}" OPENPROJECT_WORKER_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.worker.name') }}"