Commit Graph
6 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 f1308247a5 refactor(web-app-openproject): group the select queries in a folder
select-admin-state.sql joined select-ldap-auth-source-exists.sql under the shared 'select' prefix, which the prefix-grouping lint rejects. Both now live in files/sql/select/ and their three readers point there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 01:10:45 +01:00
kevinveenbirkenbachandClaude Opus 5.5 dd0d9e964d perf(web-app-openproject): apply settings and the administrator only when their digest changes
The admin step ran its Rails runner on every deploy. It now digests its sources, its inputs and the administrator and settings state OpenProject holds, compares that with the admin-provision.sha256 stamp in the instance directory, and runs only on a mismatch or when services.openproject.admin.force is set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 00:28:15 +01:00
kevinveenbirkenbachandClaude Opus 5.5 008887c0f0 perf(web-app-openproject): migrate only when the running image has not migrated the schema
db:migrate took about 24 s on every deploy. After a successful run the
deploy stamps the web container's image id as the comment of
public.schema_migrations; a deploy whose image matches the stamp skips the
migration, a new image, a failed run or a recreated database migrates. The
stamp is read unmasked because masking short config values would corrupt a
hex image id, and written through a DO/format() block because sqlfluff cannot
parse COMMENT ON ... IS with a placeholder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 00:10:22 +01:00
kevinveenbirkenbachandClaude Opus 5.5 cd28286ae6 feat(web-app-openproject): pass an older schema through every skipped major
OpenProject 17 refuses a 15.x database with IncompleteMigrationsError;
upstream requires each major in between. Before the pinned image is built
or started, the compose deploy reads schema_migrations, derives the major
that last migrated the schema from its aggregated migrations, and for each
major strictly between that and the pin stops the old containers, runs the
seeder of openproject/openproject:<major> once against the stack's
database and data volume, and works off the GoodJob queue in the same image
before GoodJob 4 takes over. A schema newer than the pin stops the deploy;
an empty database skips everything.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 10:20:22 +02:00
kevinveenbirkenbachandClaude Opus 5.5 159d7e6d01 test(web-app-openproject): accept a single probe before the gate deadline
`deadline` is whole seconds from `date +%s`. A run that starts just
before a second boundary reaches the deadline after the first probe and
one `sleep 1`, so the gate correctly gives up after one probe while the
test demanded two. With a stubbed clock (1000, 1000, 1002) the gate
probes once and prints `deadline of 2s reached`. The deadline message
already proves the pending migration held the entrypoint back; require
at least one probe.

Reported by CodeRabbit on #979.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 11:16:43 +02:00
kevinveenbirkenbachandClaude Opus 5.5 c66b79ce82 fix(web-app-openproject): probe migrations without creating tables
Swarm Nextcloud#3 on main 748189e890 (job 117182318941) wedged the
OpenProject schema: the convergence check gave up after 74 attempts
while the seeder kept exiting 1, first with
`relation "ar_internal_metadata" already exists` from its structure
load, then with `relation "announcements" already exists` on every
`db:migrate`.

The seeder (`docker/prod/seeder`) loads `db/structure.sql` through
psql, statement by statement, when `\dt` finds no relation. In swarm,
`depends_on` is ignored, so web and worker start alongside it and poll
`await_migrations.sh`. That gate called
`rails db:abort_if_pending_migrations`, which runs
`migration_context.open`, i.e. `Migrator.new`, whose constructor
executes `schema_migration.create_table` and
`internal_metadata.create_table` (Rails 8.0.4,
activerecord/lib/active_record/migration.rb:1430-1431). The seeder
saw an empty database at 05:33:20; by 05:33:38 the gate had created
`ar_internal_metadata`, the structure load aborted at line 255 with
everything alphabetically before it already committed, and every
later attempt took the migrate path into tables that already existed.

Probe with `rails db:migrate:status` instead. It aborts while
`schema_migrations` is missing and otherwise only reads the recorded
versions (database_tasks.rb:303, migration.rb:1318); the gate treats
any `down` row as pending.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 10:17:39 +02:00