OnlyOffice declares fileslibreofficeedit (and richdocuments) incompatible and
disables them on install, so the LibreOffice editor's E2E spec failed wherever
OnlyOffice was co-deployed. Enable fileslibreofficeedit only when the OnlyOffice
addon is off (addons.onlyoffice.enabled), and add the required service-coupled
addon integration hook.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Declare the 14 services that consuming roles reference but no role provided
(bigbluebutton, xwiki, openproject, gitlab, mattermost, matrix, zammad,
openwebui, flowise, peertube, moodle, suitecrm, redis, memcached) as shared
providers: set enabled/shared/bond on each entity so the service registry
registers them and the dangling references resolve.
Add test_shared_service_provider.py (lint): fail when a referenced shared
service has no provider and its name matches a role's entity/provider that does
not register it (suppressable via '# nocheck: shared-provider').
Guard the 9 web-app shared services with the run-once 01_core.yml pattern
(main.yml includes 01_core.yml only when run_once_<role> is undefined; the core
flags itself via utils/once/flag.yml) so they deploy once when pulled in by
multiple consumers. svc-db-redis/memcached are template-only (no runtime tasks).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
integration_gitlab/integration_mattermost read client_id/client_secret via
crypto->decrypt(appConfig->getValueString(lazy:true)). Provisioning set them
with 'config:app:set --sensitive', the wrong scheme -> "Authenticated
ciphertext could not be decoded" -> the connected-accounts admin page 500s,
cascading onto the discourse/matrix/mattermost addon specs.
Add set_encrypted_appconfig.php (crypto->encrypt + appConfig setValueString
lazy -- the exact scheme the apps' setEncryptedAppValue uses) and route both
provisioning hooks through it. Verified live: gitlab client_id is now an
encrypted blob and connected-accounts renders again.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Push the OpenProject OAuth credentials (authorization_method, openproject_client_id,
openproject_client_secret) into Nextcloud before the NC OAuth2 client step so the
forward connect is always provisioned. The reverse-direction Nextcloud OAuth2 client
relies on occ oauth2:add-client, which Nextcloud 33 does not ship, so it is now
failed_when: false with its dependents in a guarded block — the deploy completes
instead of aborting before the Playwright suite runs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The integration_openproject / integration_gitlab provisioning and the user_ldap
config probe read their state with tasks that always run (no when:) and
failed_when: false, so their .stdout is always defined; 'X.stdout | default('') |
trim' is identical to 'X.stdout | trim'. Remove the dead default('').
Genuinely-guarding defaults are kept: the s01 config-id fallback, the skippable
ldap auto-create stdout/stderr, the regex_search None guards, and the outer
default(..., true) fresh-or-persisted secret fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OpenProject only returns a fresh OAuth client secret when the application is first
created; on a re-deploy where the app already exists but Nextcloud never persisted
the secret (e.g. an earlier deploy failed downstream at the storage step), the
secret is unrecoverable and the provisioning assert tripped, aborting the play
before the Playwright suite ran.
ensure_nextcloud_storage.rb now destroys and recreates the OAuth application when
it exists but Nextcloud holds no secret (gated to the first call via the absent NC
client id), so a fresh secret is always emitted. The provision task passes the
persisted-secret read as NC_HAS_OP_SECRET only on that first call so the second
(client-register) call never destroys the freshly created app. Verified
in-container: the recovery path emits a fresh openproject_client_secret.
Also drops the redundant | default('') on the always-set
nextcloud_op_client_secret_current.stdout in this file.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ensure_nextcloud_storage.rb: resolve the storage creator via
User.where(admin: true) with a respond_to?(:active) guard, since OpenProject 17
removed User::STATUSES (the prior .active.first path raised NameError)
- integration_openproject_provision.yml: parse the OAuth payload with
regex_search('{.*}') instead of trim, so polluted runner stdout still yields
valid JSON
- spec: assert the provisioned OAuth client is shown in admin (both sides
coupled) and the per-user connect drives the partner /oauth/authorize with the
client_id + response_type=code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Provision a GitLab Doorkeeper OAuth application for Nextcloud and wire the
credentials into the integration_gitlab app so the per-user Connect-to-GitLab
flow reaches the partner authorize endpoint.
- provision_oauth_app.rb: create/renew the Doorkeeper app (organization_id set
to satisfy the newer GitLab oauth_applications check constraint), emit
CLIENT_ID/CLIENT_SECRET
- integration_gitlab_provision.yml: run it via gitlab-rails, parse the creds,
store them with occ config:app:set --sensitive (the app stores them encrypted)
- integration_gitlab.yml: probe the partner, read persisted creds, provision
only when the partner is up and not yet coupled
- spec: drive the real per-user OAuth connect and assert the partner
/oauth/authorize carries the provisioned client_id + response_type=code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per-addon tasks/addons hooks contain only exception logic beyond the generic loader (DRY/SPOT): config-complete/per-user integrations are documented SPOT comments; mattermost/openai/openproject/suitecrm perform genuine bidirectional OAuth/API provisioning (register client on partner, write client_id/secret back) via files/{mattermost,openproject,suitecrm} scripts, gated on the partner container running. meta/addons keys for gitlab/mastodon/matrix/peertube/zammad fixed from the inert url to the admin oauth_instance_url/instances the apps actually read.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Schema-migrate every nextcloud addon to the unified per-file addon syntax (mechanism/source/required/bridges/config); add the non-proprietary integration addons (matrix, mattermost, moodle, suitecrm, zammad) and the local gitlab bridge; wire the bridged service blocks into meta/services.yml and pin every new (service,enabled)/(service,shared) pair in meta/variants.yml for variant coverage; relocate the per-addon user_ldap hook from tasks/plugin/hooks/ to tasks/addons/ for a uniform tasks/addons/ layout, dropping the obsolete vars/plugins README.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>