Files
computer-playbook/roles/web-app-nextcloud/tasks/addons/integration_gitlab_provision.yml
kevinveenbirkenbachandClaude Opus 5 b4c37dbff7 fix(nextcloud): probe gitlab on the reach host
The readiness probe 5bd323999 added for the swarm path dialled the role's public
domain on port 80. wait_for opens a plain TCP socket from the controller, and
once 1d9d355bc gave the domain roles onion variant coverage that target became
a .onion authority, which needs Tor's SOCKS resolver and cannot be reached with
a socket. Variant 6 of run 31823845576 therefore spent the full budget on it -
"Timeout when waiting for lab.git.<onion>:80", elapsed: 600 - while the
preceding resolve_host_cid had already converged, so GitLab itself was up the
whole time.

The repository had already settled this. DOCKER_REACH_HOST
(group_vars/all/00_general.yml:47) is 127.0.0.1, swapped for the Docker bridge
gateway when the controller runs in a container, and every one of the other
eleven wait_for probes under roles/ uses it. The nearest neighbour is the same
task shape - same resolve preamble, same retries and delay - reaching its
partner as `host: DOCKER_REACH_HOST` with `ports.local.http`
(integration_openproject_provision.yml:12-17). This one was written from that
template with the host and port substituted, and the substitution is the defect.
Restoring the idiom keeps the readiness gate 5bd323999 wanted instead of
dropping it, so retries stays at 12.

The lint pins the shape, because the divergence is invisible in review: both
forms read as a plausible readiness probe, and the wrong one only fails where
the domain happens to be unroutable. It parses each wait_for block under roles/,
locates the host key by indentation, and requires DOCKER_REACH_HOST unless the
line carries `# nocheck: wait-for-reach-host` naming what the probe proves - the
opt-out a probe needs when it is verifying the ingress rather than a backend.
Checked against the original line, where it reports
integration_gitlab_provision.yml:14, and against the eleven correct probes,
which it accepts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 06:09:01 +02:00

76 lines
3.5 KiB
YAML

---
- name: "🔍 Resolve GitLab webservice hosting node + container id"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
vars:
resolve_service_key: webservice
resolve_service_name: "{{ lookup('container_service', 'web-app-gitlab', 'webservice') }}"
resolve_output_prefix: NEXTCLOUD_GITLAB
resolve_compose_cid: "{{ NEXTCLOUD_GITLAB_CONTAINER_ADDRESS }}"
resolve_converge_retries: 120
resolve_converge_delay: 5
- name: ⏳ Wait for the GitLab web endpoint
wait_for:
host: "{{ DOCKER_REACH_HOST }}"
port: "{{ lookup('config', 'web-app-gitlab', 'services.gitlab.ports.local.http') }}"
delay: 5
timeout: "{{ lookup('timeout', 600) | int }}"
- name: 🔧 Provision the GitLab OAuth application for Nextcloud and capture credentials
ansible.builtin.shell:
cmd: >-
container exec -i
-e 'NC_BASE_URL={{ nextcloud_gl_nc_base_url }}'
-e 'NC_REDIRECT_PATH=/apps/integration_gitlab/oauth-redirect'
-e 'NC_HAS_SECRET={{ nextcloud_gl_client_secret_current.stdout | trim }}'
{{ NEXTCLOUD_GITLAB_LOCAL_CID | quote }}
/srv/gitlab/bin/rails runner -e production -
stdin: "{{ lookup('file', 'ruby/addons/gitlab/provision_oauth_app.rb') }}"
delegate_to: "{{ NEXTCLOUD_GITLAB_HOST_NODE }}"
register: nextcloud_gl_provision
changed_when: "'CLIENT_ID=' in nextcloud_gl_provision.stdout"
retries: 12
delay: 5
until: nextcloud_gl_provision.rc == 0 and 'CLIENT_ID=' in nextcloud_gl_provision.stdout
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: 🔎 Parse the GitLab OAuth client id
set_fact:
nextcloud_gl_client_id: "{{ nextcloud_gl_provision.stdout | regex_search('CLIENT_ID=(.+)', '\\1') | first }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: 🔍 Resolve the GitLab OAuth client secret (freshly emitted or persisted)
set_fact:
nextcloud_gl_fresh_secret: "{{ (nextcloud_gl_provision.stdout | regex_search('CLIENT_SECRET=(.+)', '\\1') | default([], true) | first | default('', true)) | trim
}}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: 🎯 Pick the effective GitLab OAuth client secret
set_fact:
nextcloud_gl_client_secret: "{{ nextcloud_gl_fresh_secret if (nextcloud_gl_fresh_secret | length > 0) else (nextcloud_gl_client_secret_current.stdout | trim)
}}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: 🛑 Fail when no usable GitLab OAuth client secret is available
assert:
that:
- (nextcloud_gl_client_id | default('') | trim) | length > 0
- (nextcloud_gl_client_secret | default('') | trim) | length > 0
fail_msg: >-
GitLab did not return a usable OAuth application. The plaintext client secret is only
retrievable when the app is first created or its secret is renewed; reset the
integration_gitlab client_id/client_secret app config to re-provision.
- name: 🔐 Store integration_gitlab OAuth credentials Nextcloud-encrypted (ICrypto, lazy)
ansible.builtin.shell:
cmd: >-
container exec -i -u {{ NEXTCLOUD_DOCKER_USER }}
-e 'NC_APP_ID=integration_gitlab'
-e 'NC_ENC_B64={{ {'client_id': nextcloud_gl_client_id, 'client_secret': nextcloud_gl_client_secret} | to_json | b64encode }}'
{{ NEXTCLOUD_LOCAL_CID | quote }}
php
stdin: "{{ lookup('file', 'php/utils/set_encrypted_appconfig.php') }}"
register: nextcloud_gl_enc_set
changed_when: "'OK' in nextcloud_gl_enc_set.stdout"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"